"""Add sharing tables for heaps and folders Revision ID: 0011_sharing Revises: 0010_embeddings_768d Create Date: 2026-04-13 Adds heap_shares and folder_shares tables so users can share heaps and folders with other users (read or read+write). """ from typing import Sequence, Union from alembic import op import sqlalchemy as sa revision: str = "0011_sharing" down_revision: Union[str, None] = "0010_embeddings_768d" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.execute(""" CREATE TABLE IF NOT EXISTS heap_shares ( id VARCHAR NOT NULL PRIMARY KEY, heap_id VARCHAR NOT NULL REFERENCES heaps(id) ON DELETE CASCADE, owner_id VARCHAR NOT NULL REFERENCES users(id), shared_with_id VARCHAR NOT NULL REFERENCES users(id), permission VARCHAR NOT NULL DEFAULT 'read', created_at TIMESTAMP DEFAULT now(), CONSTRAINT uq_heap_share UNIQUE (heap_id, shared_with_id) ) """) op.execute("CREATE INDEX IF NOT EXISTS ix_heap_shares_shared_with ON heap_shares(shared_with_id)") op.execute("CREATE INDEX IF NOT EXISTS ix_heap_shares_heap_id ON heap_shares(heap_id)") op.execute(""" CREATE TABLE IF NOT EXISTS folder_shares ( id VARCHAR NOT NULL PRIMARY KEY, folder_id VARCHAR NOT NULL, folder_type VARCHAR NOT NULL DEFAULT 'folder', owner_id VARCHAR NOT NULL REFERENCES users(id), shared_with_id VARCHAR NOT NULL REFERENCES users(id), permission VARCHAR NOT NULL DEFAULT 'read', created_at TIMESTAMP DEFAULT now(), CONSTRAINT uq_folder_share UNIQUE (folder_id, shared_with_id) ) """) op.execute("CREATE INDEX IF NOT EXISTS ix_folder_shares_shared_with ON folder_shares(shared_with_id)") op.execute("CREATE INDEX IF NOT EXISTS ix_folder_shares_folder_id ON folder_shares(folder_id)") def downgrade() -> None: op.execute("DROP TABLE IF EXISTS folder_shares") op.execute("DROP TABLE IF EXISTS heap_shares")