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

37 statements  

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

1import secrets 

2from datetime import UTC, datetime, timedelta 

3from pathlib import Path 

4 

5import jwt 

6from sqlalchemy.orm.session import Session 

7 

8from mealie.core import root_logger 

9from mealie.core.config import get_app_settings 

10from mealie.core.security.hasher import get_hasher 

11from mealie.core.security.providers.auth_provider import AuthProvider 

12from mealie.core.security.providers.credentials_provider import CredentialsProvider 

13from mealie.core.security.providers.ldap_provider import LDAPProvider 

14from mealie.schema.user.auth import CredentialsRequest, CredentialsRequestForm 

15 

16ALGORITHM = "HS256" 

17 

18logger = root_logger.get_logger("security") 

19 

20 

21def get_auth_provider(session: Session, data: CredentialsRequestForm) -> AuthProvider: 

22 settings = get_app_settings() 

23 

24 credentials_request = CredentialsRequest(**data.__dict__) 

25 if settings.LDAP_ENABLED: 25 ↛ 26line 25 didn't jump to line 26 because the condition on line 25 was never true

26 return LDAPProvider(session, credentials_request) 

27 

28 return CredentialsProvider(session, credentials_request) 

29 

30 

31def create_access_token(data: dict, expires_delta: timedelta | None = None) -> str: 

32 settings = get_app_settings() 

33 

34 to_encode = data.copy() 

35 expires_delta = expires_delta or timedelta(hours=settings.TOKEN_TIME) 

36 

37 expire = datetime.now(UTC) + expires_delta 

38 

39 to_encode["exp"] = expire 

40 return jwt.encode(to_encode, settings.SECRET, algorithm=ALGORITHM) 

41 

42 

43def create_file_token(file_path: Path) -> str: 

44 token_data = {"file": str(file_path)} 

45 return create_access_token(token_data, expires_delta=timedelta(minutes=30)) 

46 

47 

48def create_recipe_slug_token(file_path: str | Path) -> str: 

49 token_data = {"slug": str(file_path)} 

50 return create_access_token(token_data, expires_delta=timedelta(minutes=30)) 

51 

52 

53def hash_password(password: str) -> str: 

54 """Takes in a raw password and hashes it. Used prior to saving a new password to the database.""" 

55 return get_hasher().hash(password) 

56 

57 

58def url_safe_token() -> str: 

59 """Generates a cryptographic token without embedded data. Used for password reset tokens and invitation tokens""" 

60 return secrets.token_urlsafe(24)