Skip to content

Commit d42cd5a

Browse files
authored
Verified user group (#227)
## Изменения <!-- Опишите здесь на языке, понятном каждому, изменения, сделанные в исходном коде по пунктам. --> Добавлена группа верифицированных пользователей. Туда попадают пользователи, авторизовавшиеся через oauth lkmsu ## Детали реализации <!-- Здесь можно описать технические детали по пунктам. --> При регистрации или логине через lkmsu происходит добавление юзера в группу верифицированных пользователей. При отвязывании аккаунта, юзера удаляют из группы верифицированных пользователей. Все пользователи с уже привязанными аккаунтами lkmsu будут добавлены в группу верифицированных пользователей во время миграции ## Check-List <!-- После сохранения у следующих полей появятся галочки, которые нужно проставить мышкой --> - [ ] Вы проверили свой код перед отправкой запроса? - [ ] Вы написали тесты к реализованным функциям? - [ ] Вы не забыли применить форматирование `black` и `isort` для _Back-End_ или `Prettier` для _Front-End_?
1 parent 8987255 commit d42cd5a

2 files changed

Lines changed: 98 additions & 1 deletion

File tree

auth_backend/auth_plugins/lkmsu.py

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session
1414
from auth_backend.exceptions import AlreadyExists, OauthAuthFailed
1515
from auth_backend.kafka.kafka import get_kafka_producer
16-
from auth_backend.models.db import User, UserSession
16+
from auth_backend.models.db import Group, User, UserGroup, UserSession
17+
from auth_backend.models.dynamic_settings import DynamicOption
1718
from auth_backend.schemas.types.scopes import Scope
1819
from auth_backend.settings import Settings
1920
from auth_backend.utils.security import UnionAuth
@@ -99,6 +100,7 @@ async def _register(
99100
old_user = {'user_id': user.id}
100101
new_user["user_id"] = user.id
101102
lk_id = cls.create_auth_method_param('user_id', lk_user_id, user.id, db_session=db.session)
103+
cls.assign_verified_user(user)
102104
new_user = {cls.get_name(): {"user_id": lk_id.value}}
103105
userdata = await LkmsuAuth._convert_data_to_userdata_format(userinfo)
104106
background_tasks.add_task(
@@ -153,6 +155,7 @@ async def _login(
153155
raise OauthAuthFailed(
154156
'No users found for lk msu account', 'Не найдено пользователей с таким аккаунтом LK MSU', id_token
155157
)
158+
cls.assign_verified_user(user)
156159
userdata = await LkmsuAuth._convert_data_to_userdata_format(userinfo)
157160
background_tasks.add_task(
158161
get_kafka_producer().produce,
@@ -164,6 +167,33 @@ async def _login(
164167
user, user_inp.scopes, db_session=db.session, session_name=user_inp.session_name
165168
)
166169

170+
@classmethod
171+
async def _unregister(cls, user_session: UserSession = Depends(UnionAuth(scopes=[], auto_error=True))):
172+
"""Отключает для пользователя метод входа"""
173+
user: User = user_session.user
174+
verified_group_id = DynamicOption.get("verified_group_id", session=db.session).value
175+
if verified_group_id:
176+
verified_group = Group.query(with_deleted=True, session=db.session).get(verified_group_id)
177+
if verified_group:
178+
user_group: UserGroup = (
179+
UserGroup.query(session=db.session)
180+
.filter(UserGroup.user_id == user.id, UserGroup.group_id == verified_group.id)
181+
.one_or_none()
182+
)
183+
if user_group:
184+
UserGroup.delete(user_group.id, session=db.session)
185+
else:
186+
logger.error("Verified group not found")
187+
else:
188+
logger.error("Fail to obtain verified group id")
189+
190+
old_user = {"user_id": user_session.user.id}
191+
new_user = {"user_id": user_session.user.id}
192+
old_user_params = await cls._delete_auth_methods(user_session.user, db_session=db.session)
193+
old_user[cls.get_name()] = old_user_params
194+
await AuthPluginMeta.user_updated(new_user, old_user)
195+
return None
196+
167197
@classmethod
168198
async def _redirect_url(cls):
169199
"""URL на который происходит редирект после завершения входа на стороне провайдера"""
@@ -176,6 +206,20 @@ async def _auth_url(cls):
176206
url=f'https://lk.msu.ru/oauth/authorize?response_type=code&client_id={cls.settings.LKMSU_CLIENT_ID}&redirect_uri={quote(cls.settings.LKMSU_REDIRECT_URL)}&scope=scope.profile.view'
177207
)
178208

209+
@classmethod
210+
def assign_verified_user(cls, user: User):
211+
verified_group_id = DynamicOption.get("verified_group_id", session=db.session).value
212+
if verified_group_id:
213+
verified_group = Group.query(with_deleted=True, session=db.session).get(verified_group_id)
214+
if verified_group:
215+
if verified_group not in user.groups:
216+
user.groups.append(verified_group)
217+
else:
218+
logger.error("Verified group not found")
219+
else:
220+
logger.error("Fail to obtain verified group id")
221+
return None
222+
179223
@classmethod
180224
def get_student(cls, data: dict[str, Any]) -> list[dict[str | Any]]:
181225
student: dict[str, Any] = data.get("student", {})
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
"""verified user group
2+
3+
Revision ID: 5d71a2a2405d
4+
Revises: 2d29fc132e89
5+
Create Date: 2024-11-28 00:01:19.608684
6+
7+
"""
8+
9+
import sqlalchemy as sa
10+
from alembic import op
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '5d71a2a2405d'
15+
down_revision = '2d29fc132e89'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
conn = op.get_bind()
22+
users_group_id = conn.execute(
23+
sa.text('SELECT "value_integer" FROM "dynamic_option" WHERE name=\'users_group_id\'')
24+
).scalar()
25+
26+
query = 'INSERT INTO "group" (name, parent_id, create_ts, is_deleted, update_ts) VALUES (:name, :parent_id, CURRENT_TIMESTAMP, false, CURRENT_TIMESTAMP)'
27+
conn.execute(sa.text(query).bindparams(name="verified", parent_id=users_group_id))
28+
29+
verified_group_id = conn.execute(sa.text('SELECT "id" FROM "group" WHERE name=\'verified\'')).scalar()
30+
query = 'INSERT INTO "dynamic_option" (name, value_integer, create_ts, update_ts) VALUES (:name, :value_integer, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'
31+
conn.execute(sa.text(query).bindparams(name="verified_group_id", value_integer=verified_group_id))
32+
33+
verified_user_ids = conn.execute(
34+
sa.text('SELECT "user_id" FROM "auth_method" WHERE auth_method=\'lkmsu_auth\' AND is_deleted=\'false\'')
35+
).scalars()
36+
query = 'INSERT INTO "user_group" VALUES (:user_id, :group_id, false)'
37+
for user_id in verified_user_ids:
38+
conn.execute(sa.text(query).bindparams(user_id=user_id, group_id=verified_group_id))
39+
40+
41+
def downgrade():
42+
conn = op.get_bind()
43+
try:
44+
verified_group_id, option_id = conn.execute(
45+
sa.text('SELECT "value_integer", "id" FROM "dynamic_option" WHERE "name" = \'verified_group_id\'')
46+
).one()
47+
conn.execute(
48+
sa.text('DELETE FROM "user_group" WHERE "group_id" = :group_id').bindparams(group_id=verified_group_id)
49+
)
50+
conn.execute(sa.text('DELETE FROM "group" WHERE "id" = :id').bindparams(id=verified_group_id))
51+
conn.execute(sa.text('DELETE FROM "dynamic_option" WHERE "id" = :id').bindparams(id=option_id))
52+
except Exception as e:
53+
pass

0 commit comments

Comments
 (0)