import logging from asyncio import sleep, create_task from email_validator import validate_email, EmailNotValidError from rio import Column, Component, event, Text, TextStyle, TextInput, TextInputChangeEvent, Button from src.ezgg_lan_manager import ConfigurationService, UserService, MailingService from src.ezgg_lan_manager.components.MainViewContentBox import MainViewContentBox MINIMUM_PASSWORD_LENGTH = 6 logger = logging.getLogger(__name__.split(".")[-1]) class RegisterPage(Component): pw_1: str = "" pw_2: str = "" email: str = "" user_name: str = "" pw_1_valid: bool = True pw_2_valid: bool = True email_valid: bool = True submit_button_loading: bool = False display_text: str = "" display_text_style: TextStyle = TextStyle() def on_pw_focus_loss(self, _: TextInputChangeEvent) -> None: if not (self.pw_1 == self.pw_2) or len(self.pw_1) < MINIMUM_PASSWORD_LENGTH: self.pw_1_valid = False self.pw_2_valid = False return self.pw_1_valid = True self.pw_2_valid = True def on_email_focus_loss(self, change_event: TextInputChangeEvent) -> None: try: validate_email(change_event.text, check_deliverability=False) self.email_valid = True except EmailNotValidError: self.email_valid = False def on_user_name_focus_loss(self, _: TextInputChangeEvent) -> None: current_text = self.user_name if len(current_text) > UserService.MAX_USERNAME_LENGTH: self.user_name = current_text[:UserService.MAX_USERNAME_LENGTH] async def on_submit_button_pressed(self) -> None: self.submit_button_loading = True if len(self.user_name) < 1: await self.display_animated_text(False, "Nutzername darf nicht leer sein!") self.submit_button_loading = False return if not (self.pw_1 == self.pw_2): await self.display_animated_text(False, "Passwörter stimmen nicht überein!") self.submit_button_loading = False return if len(self.pw_1) < MINIMUM_PASSWORD_LENGTH: await self.display_animated_text(False, f"Passwort muss mindestens {MINIMUM_PASSWORD_LENGTH} Zeichen lang sein!") self.submit_button_loading = False return if not self.email_valid or len(self.email) < 3: await self.display_animated_text(False, "E-Mail Adresse ungültig!") self.submit_button_loading = False return user_service = self.session[UserService] mailing_service = self.session[MailingService] lan_info = self.session[ConfigurationService].get_lan_info() if await user_service.get_user(self.email) is not None or await user_service.get_user(self.user_name) is not None: await self.display_animated_text(False, "Benutzername oder E-Mail bereits registriert!") self.submit_button_loading = False return try: new_user = await user_service.create_user(self.user_name, self.email, self.pw_1) if not new_user: logger.error(f"create_user returned: {new_user}") raise Exception(f"create_user returned: {new_user}") except Exception as e: logger.error(f"Unknown error during new user registration: {e}") await self.display_animated_text(False, "Es ist ein unbekannter Fehler aufgetreten :(") self.submit_button_loading = False return await mailing_service.send_email( subject="Erfolgreiche Registrierung", body=f"Hallo {self.user_name},\n\n" f"Du hast dich erfolgreich beim EZGG-LAN Manager für {lan_info.name} {lan_info.iteration} registriert.\n\n" f"Wenn du dich nicht registriert hast, kontaktiere bitte unser Team über unsere Homepage.\n\n" f"Liebe Grüße\nDein {lan_info.name} - Team", receiver=self.email ) self.submit_button_loading = False await self.display_animated_text(True, "Erfolgreich registriert!") @event.on_populate async def on_populate(self) -> None: await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Registrieren") async def display_animated_text(self, success: bool, text: str) -> None: self.display_text = "" style = TextStyle( fill=self.session.theme.success_color if success else self.session.theme.danger_color, font_size=0.9 ) self.display_text_style = style _ = create_task(self._animate_text(text)) async def _animate_text(self, text: str) -> None: for c in text: self.display_text += c await sleep(0.06) def build(self) -> Component: user_name_input = TextInput( label="Benutzername", text=self.bind().user_name, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, on_lose_focus=self.on_user_name_focus_loss ) email_input = TextInput( label="E-Mail Adresse", text=self.bind().email, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, on_lose_focus=self.on_email_focus_loss, is_valid=self.email_valid ) pw_1_input = TextInput( label="Passwort", text=self.bind().pw_1, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, is_secret=True, on_lose_focus=self.on_pw_focus_loss, is_valid=self.pw_1_valid ) pw_2_input = TextInput( label="Passwort wiederholen", text=self.bind().pw_2, margin_left=1, margin_right=1, margin_bottom=1, grow_x=True, is_secret=True, on_lose_focus=self.on_pw_focus_loss, is_valid=self.pw_2_valid ) submit_button = Button( content=Text( "Registrieren", style=TextStyle(fill=self.session.theme.background_color, font_size=0.9), align_x=0.5 ), grow_x=True, margin_top=2, margin_left=1, margin_right=1, margin_bottom=1, shape="rectangle", style="minor", color=self.session.theme.secondary_color, on_press=self.on_submit_button_pressed, is_loading=self.submit_button_loading ) return Column( MainViewContentBox( content=Column( Text( "Neues Konto anlegen", style=TextStyle( fill=self.session.theme.background_color, font_size=1.2 ), margin_top=2, margin_bottom=2, align_x=0.5 ), user_name_input, email_input, pw_1_input, pw_2_input, submit_button, Text(self.display_text, margin_top=2, margin_left=1, margin_right=1, margin_bottom=2, style=self.display_text_style) ) ), align_y=0, )