Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 45 additions & 1 deletion auth_backend/auth_plugins/lkmsu.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
from auth_backend.auth_method import AuthPluginMeta, OauthMeta, Session
from auth_backend.exceptions import AlreadyExists, OauthAuthFailed
from auth_backend.kafka.kafka import get_kafka_producer
from auth_backend.models.db import User, UserSession
from auth_backend.models.db import Group, User, UserGroup, UserSession
from auth_backend.models.dynamic_settings import DynamicOption
from auth_backend.schemas.types.scopes import Scope
from auth_backend.settings import Settings
from auth_backend.utils.security import UnionAuth
Expand Down Expand Up @@ -99,6 +100,7 @@ async def _register(
old_user = {'user_id': user.id}
new_user["user_id"] = user.id
lk_id = cls.create_auth_method_param('user_id', lk_user_id, user.id, db_session=db.session)
cls.assign_verified_user(user)
new_user = {cls.get_name(): {"user_id": lk_id.value}}
userdata = await LkmsuAuth._convert_data_to_userdata_format(userinfo)
background_tasks.add_task(
Expand Down Expand Up @@ -153,6 +155,7 @@ async def _login(
raise OauthAuthFailed(
'No users found for lk msu account', 'Не найдено пользователей с таким аккаунтом LK MSU', id_token
)
cls.assign_verified_user(user)
userdata = await LkmsuAuth._convert_data_to_userdata_format(userinfo)
background_tasks.add_task(
get_kafka_producer().produce,
Expand All @@ -164,6 +167,33 @@ async def _login(
user, user_inp.scopes, db_session=db.session, session_name=user_inp.session_name
)

@classmethod
async def _unregister(cls, user_session: UserSession = Depends(UnionAuth(scopes=[], auto_error=True))):
"""Отключает для пользователя метод входа"""
user: User = user_session.user
verified_group_id = DynamicOption.get("verified_group_id", session=db.session).value
if verified_group_id:
verified_group = Group.query(with_deleted=True, session=db.session).get(verified_group_id)
if verified_group:
user_group: UserGroup = (
UserGroup.query(session=db.session)
.filter(UserGroup.user_id == user.id, UserGroup.group_id == verified_group.id)
.one_or_none()
)
if user_group:
UserGroup.delete(user_group.id, session=db.session)
else:
logger.error("Verified group not found")
else:
logger.error("Fail to obtain verified group id")

old_user = {"user_id": user_session.user.id}
new_user = {"user_id": user_session.user.id}
old_user_params = await cls._delete_auth_methods(user_session.user, db_session=db.session)
old_user[cls.get_name()] = old_user_params
await AuthPluginMeta.user_updated(new_user, old_user)
return None

@classmethod
async def _redirect_url(cls):
"""URL на который происходит редирект после завершения входа на стороне провайдера"""
Expand All @@ -176,6 +206,20 @@ async def _auth_url(cls):
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'
)

@classmethod
def assign_verified_user(cls, user: User):
verified_group_id = DynamicOption.get("verified_group_id", session=db.session).value
if verified_group_id:
verified_group = Group.query(with_deleted=True, session=db.session).get(verified_group_id)
if verified_group:
if verified_group not in user.groups:
user.groups.append(verified_group)
else:
logger.error("Verified group not found")
else:
logger.error("Fail to obtain verified group id")
return None

@classmethod
def get_student(cls, data: dict[str, Any]) -> list[dict[str | Any]]:
student: dict[str, Any] = data.get("student", {})
Expand Down
53 changes: 53 additions & 0 deletions migrations/versions/5d71a2a2405d_verified_user_group.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"""verified user group

Revision ID: 5d71a2a2405d
Revises: 2d29fc132e89
Create Date: 2024-11-28 00:01:19.608684

"""

import sqlalchemy as sa
from alembic import op


# revision identifiers, used by Alembic.
revision = '5d71a2a2405d'
down_revision = '2d29fc132e89'
branch_labels = None
depends_on = None


def upgrade():
conn = op.get_bind()
users_group_id = conn.execute(
sa.text('SELECT "value_integer" FROM "dynamic_option" WHERE name=\'users_group_id\'')
).scalar()

query = 'INSERT INTO "group" (name, parent_id, create_ts, is_deleted, update_ts) VALUES (:name, :parent_id, CURRENT_TIMESTAMP, false, CURRENT_TIMESTAMP)'
conn.execute(sa.text(query).bindparams(name="verified", parent_id=users_group_id))

verified_group_id = conn.execute(sa.text('SELECT "id" FROM "group" WHERE name=\'verified\'')).scalar()
query = 'INSERT INTO "dynamic_option" (name, value_integer, create_ts, update_ts) VALUES (:name, :value_integer, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)'
conn.execute(sa.text(query).bindparams(name="verified_group_id", value_integer=verified_group_id))

verified_user_ids = conn.execute(
sa.text('SELECT "user_id" FROM "auth_method" WHERE auth_method=\'lkmsu_auth\' AND is_deleted=\'false\'')
).scalars()
query = 'INSERT INTO "user_group" VALUES (:user_id, :group_id, false)'
for user_id in verified_user_ids:
conn.execute(sa.text(query).bindparams(user_id=user_id, group_id=verified_group_id))


def downgrade():
conn = op.get_bind()
try:
verified_group_id, option_id = conn.execute(
sa.text('SELECT "value_integer", "id" FROM "dynamic_option" WHERE "name" = \'verified_group_id\'')
).one()
conn.execute(
sa.text('DELETE FROM "user_group" WHERE "group_id" = :group_id').bindparams(group_id=verified_group_id)
)
conn.execute(sa.text('DELETE FROM "group" WHERE "id" = :id').bindparams(id=verified_group_id))
conn.execute(sa.text('DELETE FROM "dynamic_option" WHERE "id" = :id').bindparams(id=option_id))
except Exception as e:
pass