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

1import typing 1abc

2 

3import bcrypt 1abc

4import mesop as me 1abc

5import mesop.labs as mel 1abc

6 

7from ...data_model import State 1abc

8from ...styles import MesopHomePageStyles 1abc

9from .basic_auth_component import basic_auth_component 1abc

10 

11if typing.TYPE_CHECKING: 1abc

12 from ..auth import AuthProtocol 

13 

14 

15class BasicAuth: # implements AuthProtocol 1abc

16 def __init__(self, allowed_users: dict[str, str]) -> None: 1abc

17 """Initialize the authentication component with allowed users. 

18 

19 Args: 

20 allowed_users (dict[str, str]): A dictionary where the keys are usernames and the values are passwords. 

21 

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

28 

29 self.allowed_users = allowed_users 1abc

30 

31 def create_security_policy(self, policy: me.SecurityPolicy) -> me.SecurityPolicy: 1abc

32 return policy 

33 

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

37 

38 def is_authorized(self, username: str, password: str) -> bool: 1abc

39 if username not in self.allowed_users: 1abc

40 return False 1abc

41 

42 password_hash = self.allowed_users[username] 1abc

43 return self._verify_password(password, password_hash) 1abc

44 

45 def on_auth_changed(self, e: mel.WebEvent) -> None: 1abc

46 state = me.state(State) 

47 

48 if e.value is None: 

49 state.authenticated_user = "" 

50 return 

51 

52 username, password = e.value["username"], e.value["password"] 

53 

54 if not self.is_authorized(username, password): 

55 raise me.MesopUserException("Invalid username or password") 

56 

57 state.authenticated_user = username 

58 

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 )