Compare commits

...

1 Commits

Author SHA1 Message Date
tcprod
3c6d903768 fix password reset with fallbackpassword 2026-02-21 00:50:30 +01:00
5 changed files with 24 additions and 14 deletions

5
sql/03-users_patch.sql Normal file
View File

@ -0,0 +1,5 @@
-- Apply this patch after using create_database.sql to extend the schema to support fallback passwords
ALTER TABLE users
ADD COLUMN user_fallback_password VARCHAR(255) DEFAULT NULL
AFTER user_password;

View File

@ -27,7 +27,7 @@ class ForgotPasswordPage(Component):
user = await user_service.get_user(self.email_input.text.strip()) user = await user_service.get_user(self.email_input.text.strip())
if user is not None: if user is not None:
new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16)) new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16))
user.user_password = sha256(new_password.encode(encoding="utf-8")).hexdigest() user.user_fallback_password = sha256(new_password.encode(encoding="utf-8")).hexdigest()
await user_service.update_user(user) await user_service.update_user(user)
await mailing_service.send_email( await mailing_service.send_email(
subject=f"Dein neues Passwort für {lan_info.name}", subject=f"Dein neues Passwort für {lan_info.name}",

View File

@ -76,14 +76,15 @@ class DatabaseService:
user_name=data[1], user_name=data[1],
user_mail=data[2], user_mail=data[2],
user_password=data[3], user_password=data[3],
user_first_name=data[4], user_fallback_password=data[4],
user_last_name=data[5], user_first_name=data[5],
user_birth_day=data[6], user_last_name=data[6],
is_active=bool(data[7]), user_birth_day=data[7],
is_team_member=bool(data[8]), is_active=bool(data[8]),
is_admin=bool(data[9]), is_team_member=bool(data[9]),
created_at=data[10], is_admin=bool(data[10]),
last_updated_at=data[11] created_at=data[11],
last_updated_at=data[12]
) )
@staticmethod @staticmethod
@ -186,10 +187,10 @@ class DatabaseService:
async with conn.cursor(aiomysql.Cursor) as cursor: async with conn.cursor(aiomysql.Cursor) as cursor:
try: try:
await cursor.execute( await cursor.execute(
"UPDATE users SET user_name=%s, user_mail=%s, user_password=%s, user_first_name=%s, " "UPDATE users SET user_name=%s, user_mail=%s, user_password=%s, user_fallback_password=%s,"
"user_last_name=%s, user_birth_date=%s, is_active=%s, is_team_member=%s, is_admin=%s " "user_first_name=%s, user_last_name=%s, user_birth_date=%s, is_active=%s, is_team_member=%s,"
"WHERE (user_id=%s)", " is_admin=%s WHERE (user_id=%s)",
(user.user_name, user.user_mail.lower(), user.user_password, (user.user_name, user.user_mail.lower(), user.user_password, user.user_fallback_password,
user.user_first_name, user.user_last_name, user.user_birth_day, user.user_first_name, user.user_last_name, user.user_birth_day,
user.is_active, user.is_team_member, user.is_admin, user.is_active, user.is_team_member, user.is_admin,
user.user_id) user.user_id)

View File

@ -59,9 +59,12 @@ class UserService:
async def is_login_valid(self, user_name_or_mail: str, password_clear_text: str) -> bool: async def is_login_valid(self, user_name_or_mail: str, password_clear_text: str) -> bool:
user = await self.get_user(user_name_or_mail) user = await self.get_user(user_name_or_mail)
user_password_hash = sha256(password_clear_text.encode(encoding="utf-8")).hexdigest()
if not user: if not user:
return False return False
return user.user_password == sha256(password_clear_text.encode(encoding="utf-8")).hexdigest() if user.user_fallback_password and user.user_fallback_password == user_password_hash:
return True
return user.user_password == user_password_hash
def _check_for_disallowed_char(self, name: str) -> Optional[str]: def _check_for_disallowed_char(self, name: str) -> Optional[str]:

View File

@ -9,6 +9,7 @@ class User:
user_name: str user_name: str
user_mail: str user_mail: str
user_password: str user_password: str
user_fallback_password: Optional[str]
user_first_name: Optional[str] user_first_name: Optional[str]
user_last_name: Optional[str] user_last_name: Optional[str]
user_birth_day: Optional[date] user_birth_day: Optional[date]