feat(auth): add DB-backed login, token management, and idempotent auth migration

This commit is contained in:
2026-04-03 12:55:34 +00:00
parent 5168e52e4b
commit 06b1805b92
28 changed files with 1609 additions and 140 deletions
+43 -3
View File
@@ -2,9 +2,10 @@
from __future__ import annotations
from datetime import datetime
from typing import Protocol
from app.domain.models import LedgerEntry, Portfolio, StrategySet, User
from app.domain.models import AuthToken, LedgerEntry, Portfolio, StrategySet, TokenPrincipal, User
class PortfolioRepository(Protocol):
@@ -12,14 +13,53 @@ class PortfolioRepository(Protocol):
def get_user(self, user_id: str) -> User: ...
def get_user_by_username(self, username: str) -> User | None: ...
def list_users(self) -> list[User]: ...
def create_user(self, username: str, *, email: str | None = None) -> User: ...
def create_user(
self,
username: str,
*,
email: str | None = None,
password_hash: str | None = None,
permission: str = "read",
is_active: bool = True,
) -> User: ...
def update_user(self, user_id: str, *, username: str | None = None, email: str | None = None) -> User: ...
def update_user(
self,
user_id: str,
*,
username: str | None = None,
email: str | None = None,
password_hash: str | None = None,
permission: str | None = None,
is_active: bool | None = None,
) -> User: ...
def delete_user(self, user_id: str) -> None: ...
def update_user_last_login(self, user_id: str) -> None: ...
def create_auth_token(
self,
user_id: str,
*,
name: str,
token_hash: str,
token_prefix: str,
permission: str,
token_type: str,
expires_at: datetime | None = None,
) -> AuthToken: ...
def list_auth_tokens(self, user_id: str) -> list[AuthToken]: ...
def revoke_auth_token(self, user_id: str, token_id: str) -> None: ...
def get_token_principal(self, token_hash: str) -> TokenPrincipal | None: ...
def get(self, portfolio_id: str) -> Portfolio: ...
def get_or_create(