bce8cd9923
一、RBAC 权限管理(角色 → 可见页面) - 新增 admin_role 表 + 权限目录 permissions.py:角色持有一组页面 key,登录后左侧只展示这些页 - 内建角色 管理员(super_admin 全权锁定)/运营/财务/技术,页集对齐原型;key 承重(require_role 用),另加中文 label 展示 - 角色 CRUD 端点(仅 super_admin)+ 目录端点;登录/me 下发当前角色有效可见页 - admins 加删除、角色存在性校验;可复看已确定登录密码:UI 建的账号留存明文 plain_password,脚本建的超管不留存 二、系统配置下发修复 - 首页数据「保存即生效」:显式保存(apply_now)对 real/manual 直接落配置目标值、绕过只增不减护栏(修「改了 app 端不变」),护栏仍管自动 tick - 首页轮播新增数据源三选一:mixed(真实优先+种子)/real(只真实)/seed(只种子),get_feed 分支 + /marquee-seeds/mode 端点 - 福利页 Tab 隐藏 任务/里程碑,及看广告的单次金币/每轮次数/信息流开关:CONFIG_DEFS 加 hidden + list_config 过滤,业务读取默认值不受影响 三、比价记录店/商品搜索 - comparison_record 加 product_names 派生列(从下单 items 拼商品名),迁移建列并回填历史行 - admin 比价记录列表店/商品分列可搜:走 product_names 普通列 LIKE,规避 SQLite JSON 中文 ensure_ascii 转义搜不到的坑 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
70 lines
2.7 KiB
Python
70 lines
2.7 KiB
Python
"""admin_role 表(RBAC 角色 → 可见页面)+ 种子内建角色
|
|
|
|
新增后台 RBAC:角色持有一组页面 key,登录后左侧只展示这些页。super_admin 内建全权(pages 存空、
|
|
effective_pages 特判为全部)、不可编辑删除;operator/finance 播默认页集,可由 super_admin 增删改。
|
|
admin_user.role 弱引用本表 name。全新环境顺序应用即得三条内建角色。
|
|
|
|
Revision ID: admin_role_table
|
|
Revises: comparison_product_names
|
|
Create Date: 2026-07-04 00:00:00.000000
|
|
"""
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects import postgresql
|
|
|
|
from alembic import op
|
|
|
|
revision: str = "admin_role_table"
|
|
down_revision: str | Sequence[str] | None = "comparison_product_names"
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
_JSON = sa.JSON().with_variant(postgresql.JSONB(), "postgresql")
|
|
|
|
# 与 app/admin/permissions.py 的 BUILTIN_ROLES 同口径(迁移内联一份,不耦合 app 常量)。
|
|
# 页集对齐 Prototypes/dashboard/permissions.md 的 ROLES。key 承重(require_role),label 为展示名。
|
|
_BUILTIN = [
|
|
{"name": "super_admin", "label": "管理员", "pages": [], "is_builtin": True},
|
|
{"name": "operator", "label": "运营", "pages": [
|
|
"dashboard", "coupon-data", "ad-revenue-report", "comparison-records",
|
|
"cps", "device-liveness", "price-reports", "feedbacks",
|
|
], "is_builtin": False},
|
|
{"name": "finance", "label": "财务", "pages": [
|
|
"dashboard", "ad-revenue-report", "cps", "withdraws",
|
|
], "is_builtin": False},
|
|
{"name": "tech", "label": "技术", "pages": [
|
|
"dashboard", "device-liveness", "config", "ad-revenue", "event-logs", "audit-logs",
|
|
], "is_builtin": False},
|
|
]
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"admin_role",
|
|
sa.Column("id", sa.Integer(), primary_key=True, autoincrement=True),
|
|
sa.Column("name", sa.String(length=32), nullable=False),
|
|
sa.Column("label", sa.String(length=32), nullable=False, server_default=""),
|
|
sa.Column("pages", _JSON, nullable=False),
|
|
sa.Column("is_builtin", sa.Boolean(), nullable=False, server_default=sa.false()),
|
|
sa.Column(
|
|
"created_at", sa.DateTime(timezone=True),
|
|
server_default=sa.func.now(), nullable=False,
|
|
),
|
|
)
|
|
op.create_index("ix_admin_role_name", "admin_role", ["name"], unique=True)
|
|
|
|
tbl = sa.table(
|
|
"admin_role",
|
|
sa.column("name", sa.String),
|
|
sa.column("label", sa.String),
|
|
sa.column("pages", _JSON),
|
|
sa.column("is_builtin", sa.Boolean),
|
|
)
|
|
op.bulk_insert(tbl, _BUILTIN)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index("ix_admin_role_name", table_name="admin_role")
|
|
op.drop_table("admin_role")
|