Skip to content

Commit ec039c6

Browse files
authored
Add self delete option (#217)
## Изменения Появляется возможность удалить своего пользователя ## Детали реализации Для удаления своего пользователя нужен скоуп `auth.self.delete` ## Check-List <!-- После сохранения у следующих полей появятся галочки, которые нужно проставить мышкой --> - [ ] Вы проверили свой код перед отправкой запроса? - [ ] Вы написали тесты к реализованным функциям? - [ ] Вы не забыли применить форматирование `black` и `isort` для _Back-End_ или `Prettier` для _Front-End_?
1 parent 6cd3a09 commit ec039c6

2 files changed

Lines changed: 34 additions & 25 deletions

File tree

auth_backend/routes/user.py

Lines changed: 27 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import logging
22
from typing import Any, Literal
33

4-
from fastapi import APIRouter, Depends, Query
4+
from fastapi import APIRouter, Depends, HTTPException, Query
55
from fastapi_sqlalchemy import db
66
from sqlalchemy.orm import Session
7+
from starlette.status import HTTP_403_FORBIDDEN
78

89
from auth_backend.auth_method import AuthPluginMeta
910
from auth_backend.auth_plugins.email import Email
@@ -141,26 +142,32 @@ async def patch_user(
141142
@user.delete("/{user_id}", response_model=None)
142143
async def delete_user(
143144
user_id: int,
144-
current_user: UserSession = Depends(UnionAuth(scopes=["auth.user.delete"], allow_none=False, auto_error=True)),
145+
current_user: UserSession = Depends(UnionAuth(scopes=[], allow_none=False, auto_error=True)),
145146
) -> None:
146147
"""
147-
Scopes: `["auth.user.delete"]`
148+
Scopes: `["auth.user.delete"]` or `["auth.user.selfdelete"]` for self delete
148149
"""
149-
logger.debug(f'User id={current_user.id} triggered delete_user')
150-
old_user = {"user_id": current_user.id}
151-
user: User = User.get(user_id, session=db.session)
150+
session_scopes = set([scope.name.lower() for scope in current_user.scopes])
151+
if "auth.user.delete" in session_scopes or (
152+
"auth.user.selfdelete" in session_scopes and user_id == current_user.user_id
153+
):
154+
logger.debug(f'User id={current_user.id} triggered delete_user')
155+
old_user = {"user_id": current_user.id}
156+
user: User = User.get(user_id, session=db.session)
152157

153-
for method in user._auth_methods:
154-
if method.is_deleted:
155-
continue
156-
# Сохраняем старое состояние пользователя
157-
if method.auth_method not in old_user:
158-
old_user[method.auth_method] = {}
159-
old_user[method.auth_method][method.param] = method.value
160-
# Удаляем AuthMethod
161-
AuthMethod.delete(method.id, session=db.session)
162-
logger.info(f'{method=} for {user.id=} deleted')
163-
User.delete(user_id, session=db.session)
164-
db.session.commit()
165-
await AuthPluginMeta.user_updated(None, old_user)
166-
logger.info(f'{user=} deleted')
158+
for method in user._auth_methods:
159+
if method.is_deleted:
160+
continue
161+
# Сохраняем старое состояние пользователя
162+
if method.auth_method not in old_user:
163+
old_user[method.auth_method] = {}
164+
old_user[method.auth_method][method.param] = method.value
165+
# Удаляем AuthMethod
166+
AuthMethod.delete(method.id, session=db.session)
167+
logger.info(f'{method=} for {user.id=} deleted')
168+
User.delete(user_id, session=db.session)
169+
db.session.commit()
170+
await AuthPluginMeta.user_updated(None, old_user)
171+
logger.info(f'{user=} deleted')
172+
else:
173+
raise HTTPException(status_code=HTTP_403_FORBIDDEN, detail="Not authorized")

tests/test_routes/test_user.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,16 +25,18 @@ def test_user_email(client: TestClient, dbsession: Session, user_factory):
2525
dbsession.commit()
2626

2727

28-
def test_delete_user(client: TestClient, dbsession: Session, user_factory):
29-
user1 = user_factory(client)
28+
def test_delete_user(client_auth: TestClient, dbsession: Session, user_factory, user_scopes):
29+
token = user_scopes[0]
30+
header = {"Authorization": token}
31+
user1 = user_factory(client_auth)
3032
time1 = datetime.utcnow()
3133
email_user = AuthMethod(user_id=user1, param="email", auth_method="email", value="testemailx@x.xy")
3234
dbsession.add(email_user)
3335
dbsession.commit()
3436
body = {"name": f"group{time1}", "parent_id": None, "scopes": []}
35-
group = client.post(url="/group", json=body).json()["id"]
36-
client.patch(f"/user/{user1}", json={"groups": [group]})
37-
resp = client.delete(f"user/{user1}")
37+
group = client_auth.post(url="/group", json=body, headers=header).json()["id"]
38+
client_auth.patch(f"/user/{user1}", json={"groups": [group]}, headers=header)
39+
resp = client_auth.delete(f"user/{user1}", headers=header)
3840
assert resp.status_code == 200
3941
user = dbsession.query(User).filter(User.id == user1).one_or_none()
4042
assert user.is_deleted

0 commit comments

Comments
 (0)