ppt-tool/backend/migrations/env.py
Vadym Samoilenko cf21ba4516 Phase 1-2: Foundation + Admin Panel & Client Management
Phase 1 (Foundation):
- Project restructure (presenton-main → backend/ + frontend/)
- Database schema (8 new models, Alembic config, seed script)
- Auth (Azure AD SSO + dev bypass, JWT sessions, AuthMiddleware)
- RBAC (access_service, rbac_middleware, admin routers)
- Audit logging (fire-and-forget, AuditMiddleware, admin router)
- i18n (react-i18next with 5 namespace files)

Phase 2 (Admin Panel & Client Management):
- Admin panel shell (sidebar layout, role guard, 12 pages)
- Redux admin slice with 18 async thunks
- User management (role changes, deactivation)
- Client management (CRUD, brand config, team management)
- Brand config editor (colors, fonts, logos, voice rules)
- Master deck upload & parser (PPTX → HTML → React pipeline)
- Audit log viewer with filters and CSV/JSON export

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 15:37:17 +00:00

75 lines
2.6 KiB
Python

import asyncio
from logging.config import fileConfig
from sqlalchemy import pool
from sqlalchemy.ext.asyncio import async_engine_from_config
from alembic import context
from sqlmodel import SQLModel
# Import ALL models so they register with SQLModel.metadata
# Existing models
from models.sql.presentation import PresentationModel # noqa: F401
from models.sql.slide import SlideModel # noqa: F401
from models.sql.key_value import KeyValueSqlModel # noqa: F401
from models.sql.image_asset import ImageAsset # noqa: F401
from models.sql.presentation_layout_code import PresentationLayoutCodeModel # noqa: F401
from models.sql.template import TemplateModel # noqa: F401
from models.sql.webhook_subscription import WebhookSubscription # noqa: F401
from models.sql.async_presentation_generation_status import AsyncPresentationGenerationTaskModel # noqa: F401
from models.sql.ollama_pull_status import OllamaPullStatus # noqa: F401
# New models
from models.sql.user import UserModel # noqa: F401
from models.sql.client import ClientModel # noqa: F401
from models.sql.team import TeamModel # noqa: F401
from models.sql.team_membership import TeamMembershipModel # noqa: F401
from models.sql.brand_config import BrandConfigModel # noqa: F401
from models.sql.master_deck import MasterDeckModel # noqa: F401
from models.sql.audit_log import AuditLogModel # noqa: F401
from models.sql.job import JobModel # noqa: F401
from utils.db_utils import get_database_url_and_connect_args
config = context.config
if config.config_file_name is not None:
fileConfig(config.config_file_name)
target_metadata = SQLModel.metadata
def run_migrations_offline() -> None:
url, _ = get_database_url_and_connect_args()
context.configure(
url=url,
target_metadata=target_metadata,
literal_binds=True,
dialect_opts={"paramstyle": "named"},
)
with context.begin_transaction():
context.run_migrations()
def do_run_migrations(connection) -> None:
context.configure(connection=connection, target_metadata=target_metadata)
with context.begin_transaction():
context.run_migrations()
async def run_migrations_online() -> None:
url, connect_args = get_database_url_and_connect_args()
connectable = async_engine_from_config(
{"sqlalchemy.url": url},
prefix="sqlalchemy.",
poolclass=pool.NullPool,
connect_args=connect_args,
)
async with connectable.connect() as connection:
await connection.run_sync(do_run_migrations)
await connectable.dispose()
if context.is_offline_mode():
run_migrations_offline()
else:
asyncio.run(run_migrations_online())