97 lines
3.1 KiB
Python
97 lines
3.1 KiB
Python
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)
|