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

29 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-10-07 03:04 +0000

1from functools import lru_cache 

2from typing import Protocol 

3 

4import bcrypt 

5 

6from mealie.core.config import get_app_settings 

7 

8 

9class Hasher(Protocol): 

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

11 

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

13 

14 

15class FakeHasher: 

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

17 return password 

18 

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

20 return password == hashed 

21 

22 

23class BcryptHasher: 

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

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

26 

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

28 password_bytes = self._get_password_bytes(password) 

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

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

31 

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

33 password_bytes = self._get_password_bytes(password) 

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

35 return bcrypt.checkpw(password_bytes, hashed_bytes) 

36 

37 

38@lru_cache(maxsize=1) 

39def get_hasher() -> Hasher: 

40 settings = get_app_settings() 

41 

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

43 return FakeHasher() 

44 

45 return BcryptHasher()