Updates
This commit is contained in:
+14
-7
@@ -2,8 +2,7 @@ from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
|
||||
from fastapi import Depends, HTTPException, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from fastapi import Depends, HTTPException, Request, status
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.orm import Session, selectinload
|
||||
|
||||
@@ -13,14 +12,14 @@ from app.core.access import (
|
||||
get_user_permissions,
|
||||
permissions_to_module_map,
|
||||
)
|
||||
from app.core.http import ADMIN_AUTH_COOKIE, CLIENT_AUTH_COOKIE, get_bearer_or_cookie_token
|
||||
from app.core.security_logging import log_security_event
|
||||
from app.core.security import verify_token
|
||||
from app.db.session import get_db
|
||||
from app.models.access import Role, User
|
||||
from app.models.client_access import ClientFeatureAccess, ClientUser
|
||||
from app.services.client_access_service import has_access_level, module_access_map
|
||||
|
||||
bearer_scheme = HTTPBearer(auto_error=False)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class AuthSession:
|
||||
@@ -67,13 +66,16 @@ def _build_internal_auth_session(db: Session, payload: dict) -> AuthSession:
|
||||
|
||||
|
||||
def get_auth_session(
|
||||
credentials: HTTPAuthorizationCredentials | None = Depends(bearer_scheme),
|
||||
request: Request,
|
||||
db: Session = Depends(get_db),
|
||||
) -> AuthSession:
|
||||
if credentials is None:
|
||||
token = get_bearer_or_cookie_token(request, cookie_name=CLIENT_AUTH_COOKIE.name) or get_bearer_or_cookie_token(
|
||||
request, cookie_name=ADMIN_AUTH_COOKIE.name
|
||||
)
|
||||
if token is None:
|
||||
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED, detail="Authentication required")
|
||||
|
||||
payload = verify_token(credentials.credentials)
|
||||
payload = verify_token(token)
|
||||
|
||||
# Internal Hunter Stock Feeds users get an auth session derived from the
|
||||
# role/permission tables rather than the client-portal ClientUser tables.
|
||||
@@ -111,6 +113,7 @@ def require_client_session(session: AuthSession = Depends(get_auth_session)) ->
|
||||
|
||||
def require_admin_session(session: AuthSession = Depends(get_auth_session)) -> AuthSession:
|
||||
if session.role != "admin":
|
||||
log_security_event("authz.denied", role=session.role, required="admin")
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Admin access required")
|
||||
return session
|
||||
|
||||
@@ -143,6 +146,7 @@ def require_client_module_access(module_key: str, minimum_level: str = "view"):
|
||||
if session.role == "internal":
|
||||
permissions = session.module_permissions or {}
|
||||
if not has_access_level(permissions.get(module_key), minimum_level):
|
||||
log_security_event("authz.denied", role=session.role, module=module_key, access_level=minimum_level)
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail=f"{module_key} access is not permitted",
|
||||
@@ -158,10 +162,12 @@ def require_client_module_access(module_key: str, minimum_level: str = "view"):
|
||||
)
|
||||
)
|
||||
if feature is not None and not feature.enabled:
|
||||
log_security_event("authz.denied", role=session.role, module=module_key, reason="feature_disabled")
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=f"{module_key} is disabled for this client")
|
||||
|
||||
permissions = module_access_map(user)
|
||||
if not has_access_level(permissions.get(module_key), minimum_level):
|
||||
log_security_event("authz.denied", role=session.role, module=module_key, access_level=minimum_level)
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail=f"{module_key} access is not permitted")
|
||||
|
||||
return AuthSession(
|
||||
@@ -190,6 +196,7 @@ def require_client_access_manager_session(
|
||||
user = load_current_client_user(db, require_client_session(session))
|
||||
permissions = module_access_map(user)
|
||||
if user.role != "superadmin" or not has_access_level(permissions.get("client_access"), "manage"):
|
||||
log_security_event("authz.denied", role=session.role, module="client_access", access_level="manage")
|
||||
raise HTTPException(status_code=status.HTTP_403_FORBIDDEN, detail="Superadmin client access is required")
|
||||
|
||||
return AuthSession(
|
||||
|
||||
Reference in New Issue
Block a user