ezgg-lan-manager/src/ez_lan_manager/components/UserEditForm.py

250 lines
9.1 KiB
Python

from datetime import date
from hashlib import sha256
from typing import Optional
from email_validator import validate_email, EmailNotValidError
from from_root import from_root
from rio import Component, Column, Button, Color, TextStyle, Text, TextInput, Row, Image, event, Spacer, DateInput, \
TextInputChangeEvent, NoFileSelectedError
from src.ez_lan_manager.services.UserService import UserService, NameNotAllowedError
from src.ez_lan_manager.services.ConfigurationService import ConfigurationService
from src.ez_lan_manager.types.SessionStorage import SessionStorage
from src.ez_lan_manager.types.User import User
class UserEditForm(Component):
is_own_profile: bool = True
profile_picture: Optional[bytes] = None
user: Optional[User] = None
input_user_name: str = ""
input_user_mail: str = ""
input_user_first_name: str = ""
input_user_last_name: str = ""
input_password_1: str = ""
input_password_2: str = ""
input_birthday: date = date.today()
is_email_valid: bool = True
result_text: str = ""
result_success: bool = True
@event.on_populate
async def on_populate(self) -> None:
await self.session.set_title(f"{self.session[ConfigurationService].get_lan_info().name} - Profil bearbeiten")
if self.is_own_profile:
self.user = await self.session[UserService].get_user(self.session[SessionStorage].user_id)
self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id)
else:
self.profile_picture = await self.session[UserService].get_profile_picture(self.user.user_id)
self.input_user_name = self.user.user_name
self.input_user_mail = self.user.user_mail
self.input_user_first_name = self.optional_str_to_str(self.user.user_first_name)
self.input_user_last_name = self.optional_str_to_str(self.user.user_last_name)
self.input_birthday = self.user.user_birth_day if self.user.user_birth_day else date.today()
@staticmethod
def optional_str_to_str(s: Optional[str]) -> str:
if s:
return s
return ""
def on_email_changed(self, change_event: TextInputChangeEvent) -> None:
try:
validate_email(change_event.text, check_deliverability=False)
self.is_email_valid = True
except EmailNotValidError:
self.is_email_valid = False
async def upload_new_pfp(self) -> None:
try:
new_pfp = await self.session.pick_file(file_types=("png", "jpg", "jpeg"), multiple=False)
except NoFileSelectedError:
self.result_text = "Keine Datei ausgewählt!"
self.result_success = False
return
if new_pfp.size_in_bytes > 2 * 1_000_000:
self.result_text = "Bild zu groß! (> 2MB)"
self.result_success = False
return
image_data = await new_pfp.read_bytes()
await self.session[UserService].set_profile_picture(self.user.user_id, image_data)
self.profile_picture = image_data
self.result_text = "Gespeichert!"
self.result_success = True
async def remove_profile_picture(self) -> None:
await self.session[UserService].remove_profile_picture(self.user.user_id)
self.profile_picture = None
self.result_text = "Profilbild entfernt!"
self.result_success = True
async def on_save_pressed(self) -> None:
if not all((self.is_email_valid, self.input_user_name, self.input_user_mail)):
self.result_text = "Ungültige Werte!"
self.result_success = False
return
if len(self.input_password_1.strip()) > 0:
if self.input_password_1.strip() != self.input_password_2.strip():
self.result_text = "Passwörter nicht gleich!"
self.result_success = False
return
self.user.user_mail = self.input_user_mail
if self.input_birthday == date.today():
self.user.user_birth_day = None
else:
self.user.user_birth_day = self.input_birthday
self.user.user_first_name = self.input_user_first_name
self.user.user_last_name = self.input_user_last_name
self.user.user_name = self.input_user_name
if len(self.input_password_1.strip()) > 0:
self.user.user_password = sha256(self.input_password_1.strip().encode(encoding="utf-8")).hexdigest()
try:
await self.session[UserService].update_user(self.user)
except NameNotAllowedError:
self.result_text = "Ungültige Zeichen in Nutzername"
self.result_success = False
return
self.result_text = "Gespeichert!"
self.result_success = True
def build(self) -> Component:
pfp_image_container = Image(
from_root("src/ez_lan_manager/assets/img/anon_pfp.png") if self.profile_picture is None else self.profile_picture,
align_x=0.5,
min_width=10,
min_height=10,
margin_top=1,
margin_bottom=1
)
return Column(
pfp_image_container,
Button(
content=Text(
"Neues Bild hochladen",
style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
),
align_x=0.5,
margin_bottom=1,
shape="rectangle",
style="major",
color="primary",
on_press=self.upload_new_pfp
) if self.is_own_profile else Button(
content=Text(
"Bild löschen",
style=TextStyle(fill=Color.from_hex("02dac5"), font_size=0.9)
),
align_x=0.5,
margin_bottom=1,
shape="rectangle",
style="major",
color="primary",
on_press=self.remove_profile_picture
),
Row(
TextInput(
label=f"{'Deine ' if self.is_own_profile else ''}User-ID",
text=str(self.user.user_id),
is_sensitive=False,
margin_left=1,
grow_x=False
),
TextInput(
label=f"{'Dein ' if self.is_own_profile else ''}Nickname",
text=self.bind().input_user_name,
is_sensitive=not self.is_own_profile,
margin_left=1,
margin_right=1,
grow_x=True
),
margin_bottom=1
),
TextInput(
label="E-Mail Adresse",
text=self.bind().input_user_mail,
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True,
is_valid=self.is_email_valid,
on_change=self.on_email_changed
),
Row(
TextInput(
label="Vorname",
text=self.bind().input_user_first_name,
margin_left=1,
margin_right=1,
grow_x=True
),
TextInput(
label="Nachname",
text=self.bind().input_user_last_name,
margin_right=1,
grow_x=True
),
margin_bottom=1
),
DateInput(
value=self.bind().input_birthday,
label="Geburtstag",
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True
),
TextInput(
label="Neues Passwort setzen",
text=self.bind().input_password_1,
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True,
is_secret=True
),
TextInput(
label="Neues Passwort wiederholen",
text=self.bind().input_password_2,
margin_left=1,
margin_right=1,
margin_bottom=1,
grow_x=True,
is_secret=True
),
Row(
Text(
text=self.bind().result_text,
style=TextStyle(fill=self.session.theme.success_color if self.result_success else self.session.theme.danger_color),
margin_left=1
),
Button(
content=Text(
"Speichern",
style=TextStyle(fill=self.session.theme.success_color, font_size=0.9),
align_x=0.2
),
align_x=0.9,
margin_top=2,
margin_bottom=1,
shape="rectangle",
style="major",
color="primary",
on_press=self.on_save_pressed
),
)
) if self.user else Spacer()