feat(admin): enforce monitoring page permissions
This commit is contained in:
@@ -10,6 +10,8 @@ from fastapi import Depends, HTTPException, Request, status
|
||||
from fastapi.security import HTTPAuthorizationCredentials, HTTPBearer
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from app.admin.permissions import ALL_PAGE_KEYS, CUSTOM_ROLE, SUPER_ADMIN_ROLE, sanitize_pages
|
||||
from app.admin.repositories import admin_role as role_repo
|
||||
from app.admin.repositories import admin_user as admin_repo
|
||||
from app.admin.security import AdminTokenError, decode_admin_token
|
||||
from app.db.session import get_db
|
||||
@@ -72,6 +74,33 @@ def require_role(*roles: str):
|
||||
return _checker
|
||||
|
||||
|
||||
def require_page(page: str):
|
||||
"""页面权限守卫依赖工厂。
|
||||
|
||||
左侧导航隐藏只是 UI,这个守卫确保直接调用 API 也必须持有对应页面权限。
|
||||
super_admin 恒通过;custom 读个人 pages_override;其余角色读 admin_role.pages。
|
||||
"""
|
||||
if page not in ALL_PAGE_KEYS:
|
||||
raise ValueError(f"unknown admin page permission: {page}")
|
||||
|
||||
def _checker(admin: CurrentAdmin, db: AdminDb) -> AdminUser:
|
||||
if admin.role == SUPER_ADMIN_ROLE:
|
||||
return admin
|
||||
pages = (
|
||||
sanitize_pages(admin.pages_override)
|
||||
if admin.role == CUSTOM_ROLE
|
||||
else role_repo.effective_pages_of(db, admin.role)
|
||||
)
|
||||
if page not in pages:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_403_FORBIDDEN,
|
||||
detail=f"page '{page}' not allowed",
|
||||
)
|
||||
return admin
|
||||
|
||||
return _checker
|
||||
|
||||
|
||||
def get_client_ip(request: Request) -> str:
|
||||
"""取客户端 IP(审计日志用)。生产经 nginx 反代,优先 X-Forwarded-For 第一段;否则直连 IP。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user