69 lines
2.1 KiB
Python
69 lines
2.1 KiB
Python
"""附件表(任务 / 工单 / 知识共用)
|
|
|
|
Revision ID: 0005
|
|
Revises: 0004
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sqlalchemy as sa
|
|
from sqlalchemy.dialects.postgresql import UUID as PgUUID
|
|
|
|
from alembic import op
|
|
|
|
from app.roles import APP_ROLE
|
|
|
|
revision = "0005"
|
|
down_revision = "0004"
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"attachment",
|
|
sa.Column("id", PgUUID(as_uuid=True), primary_key=True),
|
|
sa.Column(
|
|
"workspace_id",
|
|
PgUUID(as_uuid=True),
|
|
sa.ForeignKey("workspace.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"item_id",
|
|
PgUUID(as_uuid=True),
|
|
sa.ForeignKey("item.id", ondelete="CASCADE"),
|
|
nullable=False,
|
|
),
|
|
sa.Column(
|
|
"uploader_id",
|
|
PgUUID(as_uuid=True),
|
|
sa.ForeignKey("app_user.id", ondelete="RESTRICT"),
|
|
nullable=False,
|
|
),
|
|
sa.Column("filename", sa.String(255), nullable=False),
|
|
sa.Column("content_type", sa.String(120), nullable=False),
|
|
sa.Column("size_bytes", sa.BigInteger(), nullable=False),
|
|
sa.Column("sha256", sa.String(64), nullable=False),
|
|
sa.Column("storage_key", sa.String(255), nullable=False, unique=True),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), server_default=sa.func.now(), nullable=False),
|
|
sa.CheckConstraint("size_bytes >= 0", name="ck_attachment_size"),
|
|
)
|
|
op.create_index(
|
|
"ix_attachment_ws_item", "attachment", ["workspace_id", "item_id", "created_at"]
|
|
)
|
|
|
|
for statement in (
|
|
"ALTER TABLE attachment ENABLE ROW LEVEL SECURITY",
|
|
"CREATE POLICY attachment_isolation ON attachment "
|
|
"USING (workspace_id = app_ws_id()) WITH CHECK (workspace_id = app_ws_id())",
|
|
f"GRANT SELECT, INSERT, UPDATE, DELETE ON attachment TO {APP_ROLE}",
|
|
):
|
|
op.execute(statement)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.execute("DROP POLICY IF EXISTS attachment_isolation ON attachment")
|
|
op.drop_index("ix_attachment_ws_item", table_name="attachment")
|
|
op.drop_table("attachment")
|