Coverage for opt/mealie/lib/python3.12/site-packages/mealie/core/security/hasher.py: 83%

29 statements  

« prev     ^ index     » next       coverage.py v7.10.6, created at 2025-11-25 15:48 +0000

1from functools import lru_cache 1a

2from typing import Protocol 1a

3 

4import bcrypt 1a

5 

6from mealie.core.config import get_app_settings 1a

7 

8 

9class Hasher(Protocol): 1a

10 def hash(self, password: str) -> str: ... 10 ↛ exitline 10 didn't return from function 'hash' because 1a

11 

12 def verify(self, password: str, hashed: str) -> bool: ... 12 ↛ exitline 12 didn't return from function 'verify' because 1a

13 

14 

15class FakeHasher: 1a

16 def hash(self, password: str) -> str: 1a

17 return password 

18 

19 def verify(self, password: str, hashed: str) -> bool: 1a

20 return password == hashed 

21 

22 

23class BcryptHasher: 1a

24 def _get_password_bytes(self, password: str) -> bytes: 1a

25 return password.encode("utf-8")[:72] 1abcdefghijklmnopqrst

26 

27 def hash(self, password: str) -> str: 1a

28 password_bytes = self._get_password_bytes(password) 1ab

29 hashed = bcrypt.hashpw(password_bytes, bcrypt.gensalt()) 1ab

30 return hashed.decode("utf-8") 1ab

31 

32 def verify(self, password: str, hashed: str) -> bool: 1a

33 password_bytes = self._get_password_bytes(password) 1cdefghijklmnopqrst

34 hashed_bytes = hashed.encode("utf-8") 1cdefghijklmnopqrst

35 return bcrypt.checkpw(password_bytes, hashed_bytes) 1cdefghijklmnopqrst

36 

37 

38@lru_cache(maxsize=1) 1a

39def get_hasher() -> Hasher: 1a

40 settings = get_app_settings() 1a

41 

42 if settings.TESTING: 42 ↛ 43line 42 didn't jump to line 43 because the condition on line 42 was never true1a

43 return FakeHasher() 

44 

45 return BcryptHasher() 1a