auth für user

This commit is contained in:
Bastian Wagner
2026-08-15 21:34:40 +02:00
parent adfe14dfa8
commit f7b04337ce
11 changed files with 773 additions and 0 deletions

36
app/auth/account.py Normal file
View File

@@ -0,0 +1,36 @@
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)

View File

@@ -10,3 +10,10 @@ def password_matches(submitted: str, configured: str) -> bool:
def require_admin(request: Request) -> None:
if request.session.get("admin_authenticated") is not True:
raise HTTPException(status_code=status.HTTP_303_SEE_OTHER, headers={"Location": "/login"})
def require_self_service(request: Request) -> int:
user_id = request.session.get("self_service_user_id")
if not isinstance(user_id, int):
raise HTTPException(status_code=status.HTTP_303_SEE_OTHER, headers={"Location": "/account-login"})
return user_id