refactor: permission
This commit is contained in:
@@ -36,28 +36,19 @@ DEVELOPER_ROLE_ID = "0000000000000000000000000B"
|
||||
|
||||
PERMISSIONS: list[tuple[str, str, str]] = [
|
||||
# (permission_code, permission_name, module_code)
|
||||
("dashboard.view", "查看工作台", "dashboard"),
|
||||
("script.build", "构建脚本", "script"),
|
||||
("script.public.manage", "管理公共脚本", "script"),
|
||||
("schedule.own", "管理本人调度", "schedule"),
|
||||
("schedule.all", "管理全部调度", "schedule"),
|
||||
("experiment.own", "管理本人实验", "experiment"),
|
||||
("experiment.all", "管理全部实验", "experiment"),
|
||||
("resource.personal", "管理个人资源", "resource"),
|
||||
("resource.public.upload", "上传公共资源", "resource"),
|
||||
("resource.public.manage", "管理公共资源", "resource"),
|
||||
("system.view", "查看系统管理", "system"),
|
||||
("system.manage", "管理系统配置", "system"),
|
||||
("dashboard:view", "查看工作台", "dashboard"),
|
||||
("script:view", "查看构建脚本", "script"),
|
||||
("schedule:view", "查看调度配置", "schedule"),
|
||||
("system:view", "查看系统管理", "system"),
|
||||
("system:user:view", "查看用户管理", "system"),
|
||||
("system:project:view", "查看项目管理", "system"),
|
||||
]
|
||||
|
||||
# developer gets *.own + personal resource only; no system.*, no *.all.
|
||||
# developer gets menu-view permissions only; no system:* (admin-only).
|
||||
DEVELOPER_PERMISSION_CODES: list[str] = [
|
||||
"dashboard.view",
|
||||
"script.build",
|
||||
"script.public.manage",
|
||||
"schedule.own",
|
||||
"experiment.own",
|
||||
"resource.personal",
|
||||
"dashboard:view",
|
||||
"script:view",
|
||||
"schedule:view",
|
||||
]
|
||||
|
||||
ADMIN_PERMISSION_CODES: list[str] = [code for code, _, _ in PERMISSIONS]
|
||||
@@ -334,7 +325,6 @@ def upgrade() -> None:
|
||||
sa.Column('created_at', mysql.DATETIME(fsp=3), server_default=sa.text('CURRENT_TIMESTAMP(3)'), nullable=False),
|
||||
sa.Column('updated_at', mysql.DATETIME(fsp=3), server_default=sa.text('CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3)'), nullable=False),
|
||||
sa.Column('owner_user_id', mysql.CHAR(length=26), nullable=True),
|
||||
sa.Column('parent_object_id', mysql.CHAR(length=26), nullable=True),
|
||||
sa.Column('relative_path', sa.String(length=1024), nullable=True, comment='Workspace 相对路径'),
|
||||
sa.Column('path_hash', sa.BINARY(length=32), nullable=True, comment='SHA-256(relative_path),由应用写入'),
|
||||
sa.Column('bucket_name', sa.String(length=128), nullable=True),
|
||||
@@ -349,12 +339,11 @@ def upgrade() -> None:
|
||||
sa.Column('deleted_at', mysql.DATETIME(fsp=3), nullable=True),
|
||||
sa.Column('trash_key', sa.String(length=1100), nullable=True, comment="Path inside the trash bucket where the soft-deleted bytes live. Format: '{source_bucket}/{object_key}' so a restore is a same-key copy back to the source bucket. NULL while the row is still available."),
|
||||
sa.PrimaryKeyConstraint('storage_object_id'),
|
||||
comment='Workspace 文件和 RustFS 对象的统一元数据'
|
||||
comment='Workspace 文件和 RustFS 对象的统一元数据;目录树走 materialized path (relative_path),不要 join 邻接表列——已删除。'
|
||||
)
|
||||
op.create_index('fk_storage_created_by', 'storage_objects', ['created_by'], unique=False)
|
||||
op.create_index('idx_storage_content_hash', 'storage_objects', ['content_hash'], unique=False)
|
||||
op.create_index('idx_storage_owner', 'storage_objects', ['owner_user_id', 'object_status'], unique=False)
|
||||
op.create_index('idx_storage_parent', 'storage_objects', ['parent_object_id'], unique=False)
|
||||
op.create_index('idx_storage_workspace_path', 'storage_objects', ['workspace_id', 'storage_backend', 'path_hash'], unique=False)
|
||||
op.create_index('idx_storage_workspace_usage', 'storage_objects', ['workspace_id', 'usage_type', 'object_status'], unique=False)
|
||||
op.create_index('uk_storage_bucket_key_active', 'storage_objects', ['storage_backend', 'bucket_name', 'object_key_hash_active'], unique=True)
|
||||
@@ -693,7 +682,6 @@ def downgrade() -> None:
|
||||
op.drop_index('idx_storage_workspace_usage', table_name='storage_objects')
|
||||
op.drop_index('idx_storage_workspace_relative_path', table_name='storage_objects')
|
||||
op.drop_index('idx_storage_workspace_path', table_name='storage_objects')
|
||||
op.drop_index('idx_storage_parent', table_name='storage_objects')
|
||||
op.drop_index('idx_storage_owner', table_name='storage_objects')
|
||||
op.drop_index('idx_storage_content_hash', table_name='storage_objects')
|
||||
op.drop_index('fk_storage_created_by', table_name='storage_objects')
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
"""drop dead storage_objects.parent_object_id column and idx_storage_parent
|
||||
|
||||
Revision ID: f7a8b9c0d1e2
|
||||
Revises: e1f2a3b4c5d6
|
||||
Create Date: 2026-08-21
|
||||
|
||||
Removes a never-written column and its orphaned index. Tree structure is
|
||||
maintained entirely via relative_path (materialized path); see
|
||||
backend/src/backend/scripts.py (list_workspace_tree / list_workspace_directories).
|
||||
|
||||
MySQL 8.0 does not support DROP INDEX IF EXISTS / DROP COLUMN IF EXISTS,
|
||||
so the calls below are unconditional.
|
||||
"""
|
||||
|
||||
from collections.abc import Sequence
|
||||
|
||||
import sqlalchemy as sa
|
||||
from alembic import op
|
||||
from sqlalchemy.dialects import mysql
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = "f7a8b9c0d1e2"
|
||||
down_revision: str | Sequence[str] | None = "e1f2a3b4c5d6"
|
||||
branch_labels: str | Sequence[str] | None = None
|
||||
depends_on: str | Sequence[str] | None = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Drop the dead index, then the dead column."""
|
||||
op.drop_index("idx_storage_parent", table_name="storage_objects")
|
||||
op.drop_column("storage_objects", "parent_object_id")
|
||||
# Refresh the table comment so the warning reaches the DB, not just the ORM.
|
||||
op.execute(
|
||||
"ALTER TABLE storage_objects "
|
||||
"COMMENT = 'Workspace 文件和 RustFS 对象的统一元数据;"
|
||||
"目录树走 materialized path (relative_path),"
|
||||
"不要 join 邻接表列——已删除。'"
|
||||
)
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Recreate the column and index for rollback."""
|
||||
op.add_column(
|
||||
"storage_objects",
|
||||
sa.Column("parent_object_id", mysql.CHAR(length=26), nullable=True),
|
||||
)
|
||||
op.create_index(
|
||||
"idx_storage_parent",
|
||||
"storage_objects",
|
||||
["parent_object_id"],
|
||||
unique=False,
|
||||
)
|
||||
op.execute(
|
||||
"ALTER TABLE storage_objects "
|
||||
"COMMENT = 'Workspace 文件和 RustFS 对象的统一元数据'"
|
||||
)
|
||||
Reference in New Issue
Block a user