55from fastapi import Depends
66from fastapi .exceptions import HTTPException
77from fastapi_sqlalchemy import db
8- from starlette .status import HTTP_403_FORBIDDEN , HTTP_404_NOT_FOUND , HTTP_409_CONFLICT
8+ from starlette .status import HTTP_403_FORBIDDEN , HTTP_404_NOT_FOUND , HTTP_409_CONFLICT , HTTP_424_FAILED_DEPENDENCY
99
1010from auth_backend .auth_method .base import AuthPluginMeta
1111from auth_backend .base import Base
@@ -34,6 +34,13 @@ def __init__(self, user_id):
3434 super ().__init__ (status_code = HTTP_404_NOT_FOUND , detail = f"User id={ user_id } not linked" )
3535
3636
37+ class ConnectionIssue (HTTPException , OuterAuthException ):
38+ """Ошибка запроса к внешнему сервису"""
39+
40+ def __init__ (self , user_id ):
41+ super ().__init__ (status_code = HTTP_424_FAILED_DEPENDENCY , detail = f"User id={ user_id } not linked" )
42+
43+
3744class UserLinkingForbidden (HTTPException , OuterAuthException ):
3845 """У пользователя недостаточно прав для привязки аккаунта к внешнему сервису"""
3946
@@ -52,29 +59,38 @@ class LinkOuterAccount(Base):
5259class OuterAuthMeta (AuthPluginMeta , metaclass = ABCMeta ):
5360 """Позволяет подключить внешний сервис для синхронизации пароля"""
5461
55- __BASE_SCOPE : str
62+ _BASE_SCOPE : str
63+
64+ def __new__ (cls , * args , ** kwargs ):
65+ cls ._BASE_SCOPE = f"auth.{ cls .get_name ()} .link"
66+ logger .info (
67+ f"Init authmethod { cls .get_name ()} , scopes: %s, %s, %s" ,
68+ cls .get_scope (),
69+ cls .post_scope (),
70+ cls .delete_scope (),
71+ )
72+ return super ().__new__ (cls )
5673
5774 def __init__ (self ):
5875 super ().__init__ ()
5976 self .router .add_api_route ("/{user_id}/link" , self ._get_link , methods = ["GET" ])
6077 self .router .add_api_route ("/{user_id}/link" , self ._link , methods = ["POST" ])
61- self .router .add_api_route ("/{user_id}/unlink" , self ._unlink , methods = ["DELETE" ])
62- self .__BASE_SCOPE = f"auth.{ self .get_name ()} .link"
78+ self .router .add_api_route ("/{user_id}/link" , self ._unlink , methods = ["DELETE" ])
6379
6480 @classmethod
6581 def get_scope (cls ):
6682 """Права, необходимые пользователю для получения данных о внешнем аккаунте"""
67- return cls .__BASE_SCOPE + ".read"
83+ return cls ._BASE_SCOPE + ".read"
6884
6985 @classmethod
7086 def post_scope (cls ):
7187 """Права, необходимые пользователю для создания данных о внешнем аккаунте"""
72- return cls .__BASE_SCOPE + ".create"
88+ return cls ._BASE_SCOPE + ".create"
7389
7490 @classmethod
7591 def delete_scope (cls ):
7692 """Права, необходимые пользователю для удаления данных о внешнем аккаунте"""
77- return cls .__BASE_SCOPE + ".delete"
93+ return cls ._BASE_SCOPE + ".delete"
7894
7995 @classmethod
8096 @abstractmethod
@@ -103,34 +119,41 @@ async def on_user_update(cls, new_user: dict[str, Any], old_user: dict[str, Any]
103119
104120 Описания входных параметров соответствует параметрам `AuthMethodMeta.user_updated`.
105121 """
122+ # logger.debug("on_user_update class=%s started, new_user=%s, old_user=%s", cls.get_name(), new_user, old_user)
106123 if not new_user or not old_user :
107124 # Пользователь был только что создан или удален
108125 # Тут не будет дополнительных методов
126+ logger .debug ("%s not new_user or not old_user, closing" , cls .get_name ())
109127 return
110128
111129 user_id = new_user .get ("user_id" )
112130 password = new_user .get ("email" , {}).get ("password" )
113131 if not password :
114132 # В этом событии пароль не обновлялся, ничего не делаем
133+ logger .debug ("%s not password, closing" , cls .get_name ())
115134 return
116135
117136 username = await cls .__get_username (user_id )
118137 if not username :
119138 # У пользователя нет имени во внешнем сервисе
139+ logger .debug ("%s not username, closing" , cls .get_name ())
120140 return
121141
122142 if await cls ._is_outer_user_exists (username .value ):
143+ logger .debug ("%s user exists, changing password" , cls .get_name ())
123144 await cls ._update_outer_user_password (username .value , password )
124145 else :
125146 # Мы не нашли этого пользователя во внешнем сервисе
126147 # Разорвем связку и кинем лог
148+ logger .debug ("%s user not exists, unlinking" , cls .get_name ())
127149 username .is_deleted = True
128150 logger .error (
129151 "User id=%d has username %s, which can't be found in %s" ,
130152 user_id ,
131153 username .value ,
132154 cls .get_name (),
133155 )
156+ logger .debug ("on_user_update class=%s finished" , cls .get_name ())
134157
135158 @classmethod
136159 async def _get_link (
@@ -184,3 +207,4 @@ async def _unlink(
184207 if not username :
185208 raise UserNotLinked (user_id )
186209 username .is_deleted = True
210+ db .session .commit ()
0 commit comments