From 3ab6c18a76ecb04351cd1f4e552dc90bfbf48460 Mon Sep 17 00:00:00 2001 From: 3252a8 <3252a8@proton.me> Date: Thu, 28 May 2026 11:31:45 +0300 Subject: [PATCH] fix: preserve account language on telegram auth --- backend/bot/app/web/webapp/auth.py | 20 +++++---- tests/test_account_linking_panel.py | 66 +++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 8 deletions(-) diff --git a/backend/bot/app/web/webapp/auth.py b/backend/bot/app/web/webapp/auth.py index 89bbcd5..1627e88 100644 --- a/backend/bot/app/web/webapp/auth.py +++ b/backend/bot/app/web/webapp/auth.py @@ -1203,7 +1203,7 @@ def _apply_telegram_profile_to_user( settings: Settings, ) -> None: language_code = _normalize_language( - telegram_user.get("language_code") or user.language_code or settings.DEFAULT_LANGUAGE + user.language_code or telegram_user.get("language_code") or settings.DEFAULT_LANGUAGE ) user.telegram_id = int(telegram_user["id"]) @@ -1251,8 +1251,8 @@ async def _link_telegram_to_user( if not existing_telegram_user and int(current_user.user_id) < 0: language_code = _normalize_language( - telegram_user.get("language_code") - or current_user.language_code + current_user.language_code + or telegram_user.get("language_code") or settings.DEFAULT_LANGUAGE ) target_user, _ = await user_dal.create_user( @@ -1400,20 +1400,19 @@ async def _ensure_user_from_telegram( referral_param: Optional[str] = None, ) -> User: user_id = int(telegram_user["id"]) - language_code = _normalize_language( + telegram_language_code = _normalize_language( telegram_user.get("language_code") or settings.DEFAULT_LANGUAGE ) - update_data = { + profile_data = { "telegram_id": user_id, "username": sanitize_username(telegram_user.get("username")), "first_name": sanitize_display_name(telegram_user.get("first_name")), "last_name": sanitize_display_name(telegram_user.get("last_name")), - "language_code": language_code, } telegram_photo_url = _telegram_photo_url_value(telegram_user) if telegram_photo_url: - update_data["telegram_photo_url"] = telegram_photo_url + profile_data["telegram_photo_url"] = telegram_photo_url db_user = await user_dal.get_user_by_telegram_id(session, user_id) if not db_user: @@ -1428,7 +1427,8 @@ async def _ensure_user_from_telegram( session, { "user_id": user_id, - **update_data, + **profile_data, + "language_code": telegram_language_code, "referred_by_id": referred_by_id, "registration_date": datetime.now(timezone.utc), }, @@ -1436,6 +1436,10 @@ async def _ensure_user_from_telegram( setattr(db_user, "_webapp_created", bool(created)) return db_user + update_data = { + **profile_data, + "language_code": _normalize_language(db_user.language_code or telegram_language_code), + } changed = {key: value for key, value in update_data.items() if getattr(db_user, key) != value} if changed: db_user = await user_dal.update_user(session, db_user.user_id, changed) or db_user diff --git a/tests/test_account_linking_panel.py b/tests/test_account_linking_panel.py index 90cfd28..4f91f60 100644 --- a/tests/test_account_linking_panel.py +++ b/tests/test_account_linking_panel.py @@ -7,6 +7,8 @@ from unittest.mock import AsyncMock, patch from bot.app.web import subscription_webapp # noqa: F401 from bot.app.web.webapp import account as account_routes from bot.app.web.webapp.auth import ( + _apply_telegram_profile_to_user, + _ensure_user_from_telegram, _link_telegram_to_user, _panel_description_for_user, _sync_merged_panel_identity_for_user, @@ -97,6 +99,70 @@ class AccountLinkingPanelTests(unittest.IsolatedAsyncioTestCase): self.assertEqual(_panel_description_for_user(user), "alice??\nSmith") + def test_telegram_profile_update_preserves_existing_language(self): + user = SimpleNamespace( + telegram_id=None, + username=None, + first_name=None, + last_name=None, + language_code="ru", + telegram_photo_url=None, + ) + + _apply_telegram_profile_to_user( + user, + { + "id": 42, + "username": "alice", + "first_name": "Alice", + "last_name": "", + "language_code": "en", + }, + SimpleNamespace(DEFAULT_LANGUAGE="en"), + ) + + self.assertEqual(user.language_code, "ru") + self.assertEqual(user.username, "alice") + + async def test_telegram_login_preserves_existing_language(self): + user = SimpleNamespace( + user_id=42, + telegram_id=42, + username="old", + first_name="Old", + last_name=None, + language_code="ru", + telegram_photo_url=None, + ) + update_user = AsyncMock(return_value=user) + + with ( + patch( + "bot.app.web.webapp.auth.user_dal.get_user_by_telegram_id", + AsyncMock(return_value=user), + ), + patch( + "bot.app.web.webapp.auth.user_dal.get_user_by_id", + AsyncMock(return_value=None), + ), + patch("bot.app.web.webapp.auth.user_dal.update_user", update_user), + ): + result = await _ensure_user_from_telegram( + SimpleNamespace(), + { + "id": 42, + "username": "alice", + "first_name": "Alice", + "last_name": "", + "language_code": "en", + }, + SimpleNamespace(DEFAULT_LANGUAGE="en"), + ) + + self.assertIs(result, user) + changed = update_user.await_args.args[2] + self.assertNotEqual(changed.get("language_code"), "en") + async def test_merged_panel_identity_deletes_source_before_updating_target(self): calls = []