from __future__ import annotations from hashlib import sha256 from random import choices from typing import Any, Optional from rio import Component, Column, Row, Text, Spacer, page, Color, Rectangle, TextInput, GuardEvent, ProgressCircle from elm.types import UserSession, User from elm.services import UserService, ConfigurationService, MailingService from elm.components import ElmButton def forgot_password_page_guard(event: GuardEvent) -> Optional[str]: try: _ = event.session[UserSession].user_name return "/" except KeyError: return None @page(name="Forgot password", url_segment="lost-pw", guard=forgot_password_page_guard) class ForgotPasswordPage(Component): mail: str = "" success: bool = False is_loading: bool = False async def on_confirm(self, _: Any = None) -> None: self.is_loading = True lan_info = self.session[ConfigurationService].get_lan_info() user_service = self.session[UserService] mailing_service = self.session[MailingService] user = await user_service.get_user_by_mail(self.mail.strip()) if user is not None: new_password = "".join(choices(user_service.ALLOWED_USER_NAME_SYMBOLS, k=16)) user.user_fallback_password = sha256(new_password.encode(encoding="utf-8")).hexdigest() await User.save(user) await mailing_service.send_email( subject=f"Dein neues Passwort für {lan_info.name}", body=f"Du hast für den EZGG LAN Manager der {lan_info.name} ein neues Passwort angefragt. " f"Und hier ist es schon:\n\n{new_password}\n\nSolltest du kein neues Passwort angefordert haben, " f"ignoriere diese E-Mail.\n\nLiebe Grüße\nDein {lan_info.name} - Team", receiver=self.mail.strip() ) self.success = True self.is_loading = False def build(self) -> Component: return Row( Rectangle( content=Column( Rectangle( content=Rectangle( content=Row( Text("Passwort vergessen", margin=0.5, selectable=False, overflow="wrap", grow_x=True), ProgressCircle(min_size=1, margin=0.5, color="primary", progress=None if self.is_loading else 0) ), fill=self.session.theme.header_box_background_color, margin=0.4 ), stroke_width=0.1, stroke_color=self.session.theme.box_border_color, ), Column( TextInput( text=self.bind().mail, label="Mail Adresse", on_confirm=self.on_confirm ), Text("Prüfe deine Mails!", fill=self.session.theme.success_color, overflow="wrap", justify="center") if self.success else Spacer(grow_x=False, grow_y=False), ElmButton(text="Neues Passwort anfordern", style="small" if self.session.is_mobile() else "normal", on_press=self.on_confirm, wrap=self.session.is_mobile()), margin=1, spacing=1 ), Spacer() ), fill=self.session.theme.box_color, stroke_width=0.1, stroke_color=self.session.theme.box_border_color, min_height=15 ), align_x=0.5, align_y=0.5 )