37 lines
1.5 KiB
Python
37 lines
1.5 KiB
Python
from sqlalchemy.orm import Session
|
|
|
|
from app.auth.admin import password_matches
|
|
from app.db.models import SyncUser
|
|
from app.db.repositories import UserRepository
|
|
from app.security.credentials import CredentialCipher
|
|
|
|
|
|
def authenticate_self_service(
|
|
session: Session, cipher: CredentialCipher, email: str, password: str
|
|
) -> SyncUser | None:
|
|
"""Matches submitted email/password against any user's stored MyWhoosh OR
|
|
Garmin credentials -- decrypted and compared locally rather than
|
|
verified against the live MyWhoosh/Garmin APIs, so logging into this app
|
|
never opens a redundant upstream session (which, for MyWhoosh, would
|
|
itself trigger the "already logged in from another device" conflict)."""
|
|
submitted_email = email.strip()
|
|
if not submitted_email or not password:
|
|
return None
|
|
for user in UserRepository(session).list_all():
|
|
if _credential_matches(cipher, user.mywhoosh_email_enc, user.mywhoosh_password_enc, submitted_email, password):
|
|
return user
|
|
if _credential_matches(cipher, user.garmin_email_enc, user.garmin_password_enc, submitted_email, password):
|
|
return user
|
|
return None
|
|
|
|
|
|
def _credential_matches(
|
|
cipher: CredentialCipher, email_enc: str, password_enc: str, submitted_email: str, submitted_password: str
|
|
) -> bool:
|
|
try:
|
|
stored_email = cipher.decrypt(email_enc)
|
|
stored_password = cipher.decrypt(password_enc)
|
|
except ValueError:
|
|
return False
|
|
return stored_email == submitted_email and password_matches(submitted_password, stored_password)
|