from __future__ import annotations from dataclasses import dataclass from sqlalchemy.orm import Session from app.db.base import Base from app.db.models import Role, Tenant, User from app.db.session import engine from app.security.api_keys import CreatedApiKey, create_api_key DEFAULT_SCOPES = [ "campaign:read", "campaign:write", "campaign:validate", "campaign:build", "campaign:queue", "campaign:send_test", "campaign:send", "attachments:read", "attachments:write", "reports:read", "reports:send", "audit:read", "admin:users", "admin:settings", ] DEFAULT_ROLES = { "owner": ["*"], "admin": [ "campaign:read", "campaign:write", "campaign:validate", "campaign:build", "campaign:queue", "campaign:send_test", "campaign:send", "attachments:read", "attachments:write", "reports:read", "reports:send", "audit:read", "admin:users", "admin:settings", ], "campaign_manager": ["campaign:read", "campaign:write", "campaign:validate", "campaign:build", "reports:read"], "sender": ["campaign:read", "campaign:queue", "campaign:send_test", "campaign:send", "reports:read", "reports:send"], "reviewer": ["campaign:read", "campaign:validate", "reports:read"], "viewer": ["campaign:read", "reports:read"], "auditor": ["campaign:read", "reports:read", "audit:read"], } @dataclass(slots=True) class BootstrapResult: tenant: Tenant user: User created_api_key: CreatedApiKey | None def create_all_tables() -> None: # Import models so SQLAlchemy sees all tables. from app.db import models # noqa: F401 Base.metadata.create_all(bind=engine) def bootstrap_dev_data( session: Session, *, api_key_secret: str | None = None, tenant_slug: str = "default", user_email: str = "admin@example.local", ) -> BootstrapResult: tenant = session.query(Tenant).filter(Tenant.slug == tenant_slug).one_or_none() if tenant is None: tenant = Tenant(slug=tenant_slug, name="Default Tenant") session.add(tenant) session.flush() for slug, permissions in DEFAULT_ROLES.items(): role = session.query(Role).filter(Role.tenant_id == tenant.id, Role.slug == slug).one_or_none() if role is None: session.add(Role(tenant_id=tenant.id, slug=slug, name=slug.replace("_", " ").title(), permissions=permissions)) user = session.query(User).filter(User.tenant_id == tenant.id, User.email == user_email).one_or_none() if user is None: user = User(tenant_id=tenant.id, email=user_email, display_name="Development Admin", is_tenant_admin=True) session.add(user) session.flush() created_api_key = None if api_key_secret: existing = [key for key in user.api_keys if key.name == "Development API key" and key.revoked_at is None] if not existing: created_api_key = create_api_key( session, user=user, name="Development API key", scopes=["*"], secret=api_key_secret, ) session.commit() return BootstrapResult(tenant=tenant, user=user, created_api_key=created_api_key)