"""sys_role_permission 附件四权限列与方案锁挂载位合并(契约1.41)。 Revision ID: 0039_attachment_permissions_lock_merge Revises: 0038_session_jti Create Date: 2026-09-18 变更要点(仅库结构同步,Python 版已废弃不做功能实现): 1. sys_role_permission 加 4 列:can_attachment_view / can_attachment_download / can_attachment_edit / can_attachment_upload——附件权限独立于主案权限, 不跟随挂载主案权限;仅 OWN 行有意义(OTHER 行服务端拒绝置真); 2. doc_document 方案锁「挂载/解除挂载」合并为单一「挂载」保护位:存量 protect_unbind_attachment=1 并入 protect_bind_attachment(列保留); 3. 双引擎幂等:先探测列存在再加(MySQL 与达梦升级互不冲突)。 """ from __future__ import annotations from collections.abc import Sequence import sqlalchemy as sa from alembic import op revision: str = "0039_attachment_permissions_lock_merge" down_revision: str | None = "0038_session_jti" branch_labels: str | Sequence[str] | None = None depends_on: str | Sequence[str] | None = None _ATTACHMENT_COLUMNS = ( "can_attachment_view", "can_attachment_download", "can_attachment_edit", "can_attachment_upload", ) def _column_exists(table: str, column: str) -> bool: # 达梦 inspector 返回大写名,统一小写比较 inspector = sa.inspect(op.get_bind()) return column.lower() in { name.lower() for name in inspector.get_columns(table) } def upgrade() -> None: for column in _ATTACHMENT_COLUMNS: if _column_exists("sys_role_permission", column): continue op.add_column( "sys_role_permission", sa.Column(column, sa.Boolean(), nullable=False, server_default=sa.false()), ) op.execute( "UPDATE doc_document SET protect_bind_attachment = 1 " "WHERE protect_unbind_attachment = 1 AND protect_bind_attachment = 0" ) def downgrade() -> None: for column in reversed(_ATTACHMENT_COLUMNS): if not _column_exists("sys_role_permission", column): continue op.drop_column("sys_role_permission", column)