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
« 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
4import bcrypt
6from mealie.core.config import get_app_settings
9class Hasher(Protocol):
10 def hash(self, password: str) -> str: ... 10 ↛ exitline 10 didn't return from function 'hash' because
12 def verify(self, password: str, hashed: str) -> bool: ... 12 ↛ exitline 12 didn't return from function 'verify' because
15class FakeHasher:
16 def hash(self, password: str) -> str:
17 return password
19 def verify(self, password: str, hashed: str) -> bool:
20 return password == hashed
23class BcryptHasher:
24 def _get_password_bytes(self, password: str) -> bytes:
25 return password.encode("utf-8")[:72]
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")
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)
38@lru_cache(maxsize=1)
39def get_hasher() -> Hasher:
40 settings = get_app_settings()
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()
45 return BcryptHasher()