后台:新增监控审计权限分组并加强接口鉴权 (#159)
## 变更 - 权限目录新增一级分组“监控审计”,统一设备存活、埋点成功率、埋点日志和审计日志。 - 补齐 `analytics-health` 页面权限,技术角色默认拥有四项监控审计权限;运营默认仅保留设备存活。 - 新增服务端 `require_page` 守卫,四组 API 不再只依赖前端隐藏导航,直接调用也会校验角色或个人页面权限。 - 增加迁移,为存量技术角色补上 `analytics-health` 权限,并同步接口文档。 ## 验证 - 改动文件 `ruff check` 通过。 - `tests/test_admin_roles.py tests/test_analytics_health.py`: 24 passed。 - Alembic 从空库 upgrade 到 head,再 downgrade 本迁移:通过。 - 全量测试:443 passed、6 failed;6 项失败在干净 `origin/main` 上原样复现(主干为 442 passed、6 failed),与本 PR 无关。 --------- Co-authored-by: unknown <798648091@qq.com> Reviewed-on: #159 Co-authored-by: linkeyu <linkeyu@wonderable.ai> Co-committed-by: linkeyu <linkeyu@wonderable.ai>
This commit was merged in pull request #159.
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