inital commit

This commit is contained in:
2026-06-08 15:57:11 +02:00
parent aaf8729663
commit d9ca48addc
114 changed files with 12172 additions and 1 deletions

View File

@@ -0,0 +1,96 @@
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)