Phase 2: Visibility Filter & Owner ID
Check Cross-Plugin Imports / check (push) Has been cancelled

- Add OwnedMixin to 15 models (contact_folder, user_preference, workspace,
  mcp_server_config, agent_definition, automation_definition, report_template,
  report_instance, entity_link, comm_conversation, proactive_suggestion,
  ai_agent, ai_chat_session, tag, share_link)
- Migration 0102: Add owner_id column to 15 tables with backfill from user_id
- Fix EntityPermission Registry: remove notification, add entity_attachment,
  entity_history, subtask, calendar, folder; fix wrong class names
  (DmsFile→File, CalendarEvent→CalendarEntry, Mailbox→MailAccount)
- Add apply_visibility_filter to list endpoints in tags, tasks, mcp_client,
  automation, report_generator, ai_assistant routes
- Add owner_id to create handlers for all new OwnedMixin models
- Patch tasks/services.py and automation/services.py list methods with
  user_id and is_system_admin parameters
This commit is contained in:
Agent Zero
2026-08-04 00:03:29 +02:00
parent 93a330ae40
commit e17b9c9e56
29 changed files with 391 additions and 36 deletions
@@ -0,0 +1,69 @@
"""Add owner_id column to Phase 2 tables for row-level ownership.
Adds nullable owner_id (FK → users.id, ON DELETE SET NULL) to tables
that gained OwnedMixin in Phase 2. For tables that already have a
non-nullable user_id column, owner_id is backfilled from user_id.
Revision ID: 0102
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID as PGUUID
revision = "0102"
down_revision = "0101"
branch_labels = None
depends_on = None
# (table_name, has_user_id_to_backfill)
TABLES = [
# Core models
("contact_folders", True),
("user_preferences", True),
("workspaces", False),
# Plugin models
("mcp_server_configs", False),
("automation_agent_definitions", False),
("automation_definitions", False),
("report_templates", False),
("report_instances", False),
("entity_links", False),
("comm_conversations", False),
("ai_proactive_suggestions", True),
("ai_agents", False),
("ai_chat_sessions", True),
("tags", False),
("share_links", True),
]
def upgrade() -> None:
for table_name, _has_user_id in TABLES:
op.add_column(
table_name,
sa.Column(
"owner_id",
PGUUID(as_uuid=True),
sa.ForeignKey("users.id", ondelete="SET NULL"),
nullable=True,
),
)
op.create_index(
f"ix_{table_name}_owner_id",
table_name,
["owner_id"],
)
# Backfill owner_id from user_id where available
for table_name, has_user_id in TABLES:
if has_user_id:
op.execute(
f"UPDATE {table_name} SET owner_id = user_id WHERE owner_id IS NULL;"
)
def downgrade() -> None:
for table_name, _ in TABLES:
op.drop_index(f"ix_{table_name}_owner_id", table_name=table_name)
op.drop_column(table_name, "owner_id")