Skip to content

Commit 63fcdb0

Browse files
committed
Add start settings.
1 parent 989e7c3 commit 63fcdb0

1 file changed

Lines changed: 108 additions & 0 deletions

File tree

auth_backend/auth_plugins/telegram.py

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,3 +185,111 @@ async def _convert_data_to_userdata_format(cls, data: dict[str, Any]) -> UserLog
185185
]
186186
result = {"items": items, "source": cls.get_name()}
187187
return cls.userdata_process_empty_strings(UserLogin.model_validate(result))
188+
189+
190+
class NewTelegramSettings(Settings):
191+
TELEGRAM_REDIRECT_URL: str = "https://app.test.profcomff.com/auth"
192+
TELEGRAM_BOT_TOKEN: str | None = None # TODO: добавить сюда токен бота для тестов. В целом, брать его из .env.
193+
194+
195+
class NewTelegramAuth(OauthMeta):
196+
"""Вход в приложение 'Твой ФФ' через Telegram Login Widget."""
197+
prefix = '/telegram'
198+
tags = ['Telegram']
199+
settings = NewTelegramSettings()
200+
201+
class TGAuthResponseSchema(BaseModel):
202+
# id_token: str | None = Field(default=None, help="Telegram JWT token identifier")
203+
id: str
204+
first_name: str
205+
last_name: str | None = None
206+
username: str | None = None
207+
photo_url: str | None = None
208+
auth_date: str
209+
hash: str
210+
# scopes: list[Scope] | None = None
211+
# session_name: str | None = None
212+
213+
@classmethod
214+
async def _register(
215+
cls,
216+
user_inp: TGAuthResponseSchema,
217+
background_tasks: BackgroundTasks,
218+
user_session: UserSession = Depends(UnionAuth(auto_error=True, scopes=[], allow_none=True)),
219+
) -> Session:
220+
old_user = None
221+
new_user = {}
222+
223+
# Проверяем получение корректных данных
224+
userinfo = await cls._check(user_inp)
225+
tg_user_id = userinfo['id']
226+
227+
# if user_inp.id_token is None:
228+
# userinfo = await cls._check(user_inp)
229+
# telegram_user_id = user_inp.id
230+
# logger.debug(userinfo)
231+
# else:
232+
# userinfo = jwt.decode(user_inp.id_token, cls.settings.ENCRYPTION_KEY, algorithms=["HS256"])
233+
# telegram_user_id = userinfo['id']
234+
# logger.debug(userinfo)
235+
236+
# Проверяем, что этот тг-аккаунт уже не привязан к существующему пользователю! # TODO: уточнить, что это правда так работает...
237+
user = await cls._get_user('user_id', tg_user_id, db_session=db.session)
238+
if user is not None:
239+
raise AlreadyExists(User, user.id)
240+
241+
if user_session is None:
242+
user = await cls._create_user(db_session=db.session) # if user_session is None else user_session.user
243+
else:
244+
user = user_session.user
245+
old_user = {'user_id': user.id}
246+
new_user["user_id"] = user.id
247+
tg_auth = cls.create_auth_method_param('user_id', tg_user_id, user.id, db_session=db.session)
248+
new_user[cls.get_name()] = {"user_id": tg_auth.value}
249+
userdata = await TelegramAuth._convert_data_to_userdata_format(userinfo)
250+
background_tasks.add_task(
251+
get_kafka_producer().produce,
252+
cls.settings.KAFKA_USER_LOGIN_TOPIC_NAME,
253+
TelegramAuth.generate_kafka_key(user.id),
254+
userdata,
255+
)
256+
await AuthPluginMeta.user_updated(new_user, old_user)
257+
return await cls._create_session(
258+
user, # TODO: спросить, зачем (в google.py) отправляется новая сессия с user. user обновляется к этому моменту? Даже если меняется, то зачем именно здесь пользователю новая сессия?
259+
user_inp.scopes,
260+
db_session=db.session,
261+
session_name=user_inp.session_name,
262+
)
263+
264+
@classmethod
265+
async def _redirect_url(cls):
266+
"""URL на который происходит редирект после завершения входа на стороне провайдера"""
267+
return OauthMeta.UrlSchema(url=cls.settings.TELEGRAM_REDIRECT_URL)
268+
269+
@classmethod
270+
async def _check(cls, user_inp): # TODO: перепроверить, что написанное реально поддерживает проверку по доке тг!
271+
'''Проверка данных пользователя
272+
273+
https://core.telegram.org/widgets/login#checking-authorization
274+
'''
275+
data_check = {
276+
'id': user_inp.id,
277+
'first_name': user_inp.first_name,
278+
'last_name': user_inp.last_name,
279+
'username': user_inp.username,
280+
'photo_url': user_inp.photo_url,
281+
'auth_date': user_inp.auth_date,
282+
}
283+
check_hash = user_inp.hash
284+
data_check_string = ''
285+
for k, v in sorted(data_check.items()):
286+
if v is None:
287+
continue
288+
data_check_string += f'{unquote(k)}={unquote(v)}\n'
289+
data_check_string = data_check_string.rstrip('\n')
290+
secret_key = hashlib.sha256(str.encode(cls.settings.TELEGRAM_BOT_TOKEN)).digest()
291+
signing = hmac.new(secret_key, msg=str.encode(data_check_string), digestmod=hashlib.sha256).hexdigest()
292+
if signing == check_hash:
293+
return data_check
294+
else:
295+
raise OauthAuthFailed('Invalid user data from Telegram', 'Неправильные учетные данные')

0 commit comments

Comments
 (0)