forked from ZhuLinsen/daily_stock_analysis
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathauth.py
More file actions
88 lines (67 loc) · 2.29 KB
/
Copy pathauth.py
File metadata and controls
88 lines (67 loc) · 2.29 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# -*- coding: utf-8 -*-
"""
Auth middleware: protect /api/v1/* when users exist in the system.
When no users have registered yet, all endpoints are open.
"""
from __future__ import annotations
import logging
from typing import Callable
from fastapi import Request
from fastapi.responses import JSONResponse
from starlette.middleware.base import BaseHTTPMiddleware
from src.auth import COOKIE_NAME, verify_session_user
logger = logging.getLogger(__name__)
EXEMPT_PATHS = frozenset({
"/api/v1/auth/login",
"/api/v1/auth/register",
"/api/v1/auth/status",
"/api/v1/auth/logout",
"/api/v1/auth/forgot-password",
"/api/v1/auth/reset-password",
"/api/health",
"/health",
"/docs",
"/redoc",
"/openapi.json",
})
EXEMPT_PREFIXES = (
"/api/v1/share/", # public share links
)
def _path_exempt(path: str) -> bool:
normalized = path.rstrip("/") or "/"
if normalized in EXEMPT_PATHS:
return True
for prefix in EXEMPT_PREFIXES:
if normalized.startswith(prefix):
return True
return False
def has_users() -> bool:
"""Check if any users are registered. Lazy import to avoid circular deps."""
from src.storage import DatabaseManager, User
try:
db = DatabaseManager.get_instance()
with db.get_session() as session:
return session.query(User.id).first() is not None
except Exception:
return False
class AuthMiddleware(BaseHTTPMiddleware):
"""Require valid user session for /api/v1/* when users exist."""
async def dispatch(self, request: Request, call_next: Callable):
path = request.url.path
if not path.startswith("/api/v1/"):
return await call_next(request)
if _path_exempt(path):
return await call_next(request)
if not has_users():
return await call_next(request)
cookie_val = request.cookies.get(COOKIE_NAME)
user_id = verify_session_user(cookie_val) if cookie_val else None
if not user_id:
return JSONResponse(
status_code=401,
content={"error": "unauthorized", "message": "Login required"},
)
request.state.user_id = user_id
return await call_next(request)
def add_auth_middleware(app):
app.add_middleware(AuthMiddleware)