fda82fe313
## 变更 - 权限目录新增一级分组“监控审计”,统一设备存活、埋点成功率、埋点日志和审计日志。 - 补齐 `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>
57 lines
1.5 KiB
Python
57 lines
1.5 KiB
Python
"""补齐监控审计页面权限。
|
|
|
|
Revision ID: monitoring_audit_rbac
|
|
Revises: merge_signin_boost_main
|
|
Create Date: 2026-07-22 00:00:00.000000
|
|
"""
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
from alembic import op
|
|
|
|
revision: str = "monitoring_audit_rbac"
|
|
down_revision: str | Sequence[str] | None = "merge_signin_boost_main"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
_JSON = sa.JSON().with_variant(postgresql.JSONB(), "postgresql")
|
|
_PAGE = "analytics-health"
|
|
|
|
|
|
def _role_table() -> sa.TableClause:
|
|
return sa.table(
|
|
"admin_role",
|
|
sa.column("name", sa.String),
|
|
sa.column("pages", _JSON),
|
|
)
|
|
|
|
|
|
def upgrade() -> None:
|
|
role = _role_table()
|
|
conn = op.get_bind()
|
|
pages = conn.execute(
|
|
sa.select(role.c.pages).where(role.c.name == "tech")
|
|
).scalar_one_or_none()
|
|
if pages is not None and _PAGE not in pages:
|
|
conn.execute(
|
|
role.update()
|
|
.where(role.c.name == "tech")
|
|
.values(pages=[*pages, _PAGE])
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
role = _role_table()
|
|
conn = op.get_bind()
|
|
pages = conn.execute(
|
|
sa.select(role.c.pages).where(role.c.name == "tech")
|
|
).scalar_one_or_none()
|
|
if pages is not None and _PAGE in pages:
|
|
conn.execute(
|
|
role.update()
|
|
.where(role.c.name == "tech")
|
|
.values(pages=[page for page in pages if page != _PAGE])
|
|
)
|