feat: M1 foundation — compose stack, FastAPI, Google OAuth, encrypted tokens
- docker-compose with Postgres 16 + slim Python API image - FastAPI app with session middleware, health endpoint, static login page - Google OAuth (Authlib) with email invite-list whitelist; admin role support - User + OAuthToken models; refresh tokens encrypted at rest (Fernet) - Alembic migrations, run automatically on container startup - Postgres backup/restore scripts for portability between machines
This commit is contained in:
commit
3a5209e96c
27 changed files with 775 additions and 0 deletions
25
backend/app/security.py
Normal file
25
backend/app/security.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from cryptography.fernet import Fernet
|
||||
|
||||
from app.config import settings
|
||||
|
||||
_fernet: Fernet | None = (
|
||||
Fernet(settings.token_encryption_key.encode()) if settings.token_encryption_key else None
|
||||
)
|
||||
|
||||
|
||||
def _require_fernet() -> Fernet:
|
||||
if _fernet is None:
|
||||
raise RuntimeError("TOKEN_ENCRYPTION_KEY is not configured")
|
||||
return _fernet
|
||||
|
||||
|
||||
def encrypt(value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
return _require_fernet().encrypt(value.encode()).decode()
|
||||
|
||||
|
||||
def decrypt(value: str | None) -> str | None:
|
||||
if value is None:
|
||||
return None
|
||||
return _require_fernet().decrypt(value.encode()).decode()
|
||||
Loading…
Add table
Add a link
Reference in a new issue