Coverage for fastagency/ui/mesop/auth/basic_auth/basic_auth.py: 33%
22 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-19 12:16 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-04-19 12:16 +0000
1import typing 1abc
3import bcrypt 1abc
4import mesop as me 1abc
5import mesop.labs as mel 1abc
7from ...data_model import State 1abc
8from ...styles import MesopHomePageStyles 1abc
9from .basic_auth_component import basic_auth_component 1abc
11if typing.TYPE_CHECKING: 1abc
12 from ..auth import AuthProtocol
15class BasicAuth: # implements AuthProtocol 1abc
16 def __init__(self, allowed_users: dict[str, str]) -> None: 1abc
17 """Initialize the authentication component with allowed users.
19 Args:
20 allowed_users (dict[str, str]): A dictionary where the keys are usernames and the values are passwords.
22 Initializes:
23 _self (AuthProtocol): Ensures the instance conforms to the AuthProtocol interface.
24 allowed_users (dict[str, str]): A dictionary where the keys are usernames and the values are hashed passwords.
25 """
26 # mypy check if self is AuthProtocol
27 _self: AuthProtocol = self 1abc
29 self.allowed_users = allowed_users 1abc
31 def create_security_policy(self, policy: me.SecurityPolicy) -> me.SecurityPolicy: 1abc
32 return policy
34 def _verify_password(self, password: str, password_hash: str) -> bool: 1abc
35 """Verify a password against its hash."""
36 return bcrypt.checkpw(password.encode("utf-8"), password_hash.encode("utf-8")) 1abc
38 def is_authorized(self, username: str, password: str) -> bool: 1abc
39 if username not in self.allowed_users: 1abc
40 return False 1abc
42 password_hash = self.allowed_users[username] 1abc
43 return self._verify_password(password, password_hash) 1abc
45 def on_auth_changed(self, e: mel.WebEvent) -> None: 1abc
46 state = me.state(State)
48 if e.value is None:
49 state.authenticated_user = ""
50 return
52 username, password = e.value["username"], e.value["password"]
54 if not self.is_authorized(username, password):
55 raise me.MesopUserException("Invalid username or password")
57 state.authenticated_user = username
59 # maybe me.Component is wrong
60 def auth_component(self) -> me.component: 1abc
61 styles = MesopHomePageStyles()
62 state = me.state(State)
63 if state.authenticated_user:
64 with me.box(style=styles.logout_btn_container):
65 basic_auth_component(
66 on_auth_changed=self.on_auth_changed,
67 authenticated_user=state.authenticated_user,
68 )
69 else:
70 with me.box(style=styles.login_box): # noqa: SIM117
71 with me.box(style=styles.login_btn_container):
72 basic_auth_component(
73 on_auth_changed=self.on_auth_changed,
74 authenticated_user=state.authenticated_user,
75 )