e518bce922
Resolve all merge conflicts between our automation feature branch and current main (v0.163.0, 920 commits ahead). Conflicts resolved: - app/api/__init__.py: add automation_router alongside main's new routers (classification_rules, qr_auth, sessions, system_reset) - app/config.py: add main's new settings (dropbox_use_global_credentials, factory_reset_on_startup, enable_factory_reset) - app/models.py: add main's new models (ClassificationRuleModel, UserSession, QRLoginChallenge, SharePoint integration type) - app/utils/settings_service.py: merge automation_hooks_enabled with main's new metadata entries - docs/API.md: merge automation API docs with main's classification rules docs - docs/ConfigurationGuide.md: add factory reset settings - tests/conftest.py: import both AutomationHook and new main models Migration renumbered: - 037_add_automation_hooks → 040_add_automation_hooks - down_revision: 039_add_classification_rules (was 036_add_document_translation_fields) - Chain: 036 → 037 → 038 → 039 → 040 (automation hooks) For all non-automation files with conflicts, main's version was taken since our branch did not modify those files (conflicts were from a stale prior merge). Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/DocuElevate/sessions/cb62f012-3b69-4415-835e-3857ce3e9f45
129 lines
3.7 KiB
Python
129 lines
3.7 KiB
Python
"""Alembic environment configuration for DocuElevate.
|
||
|
||
This module configures Alembic to use the application's database URL
|
||
from ``app.config.settings`` and the SQLAlchemy ``Base.metadata`` so
|
||
that autogenerate can detect model changes.
|
||
|
||
It also supports receiving an existing connection via
|
||
``config.attributes["connection"]`` for programmatic invocation from
|
||
``app.database.init_db()``, which is essential for in-memory SQLite
|
||
databases used in testing.
|
||
"""
|
||
|
||
from logging.config import fileConfig
|
||
|
||
from alembic import context
|
||
from sqlalchemy import engine_from_config, pool
|
||
|
||
# Import application Base and models so target_metadata reflects the full schema.
|
||
from app.database import Base
|
||
|
||
# Ensure all models are imported so Base.metadata is populated.
|
||
from app.models import ( # noqa: F401
|
||
ApiToken,
|
||
ApplicationSettings,
|
||
AuditLog,
|
||
BackupRecord,
|
||
ClassificationRuleModel,
|
||
ComplianceTemplate,
|
||
DocumentMetadata,
|
||
FileProcessingStep,
|
||
FileRecord,
|
||
ImapIngestionProfile,
|
||
InAppNotification,
|
||
LocalUser,
|
||
MobileDevice,
|
||
Pipeline,
|
||
PipelineRoutingRule,
|
||
PipelineStep,
|
||
ProcessingLog,
|
||
SavedSearch,
|
||
ScheduledJob,
|
||
SettingsAuditLog,
|
||
SharedLink,
|
||
SubscriptionPlan,
|
||
UserImapAccount,
|
||
UserIntegration,
|
||
UserNotificationPreference,
|
||
UserNotificationTarget,
|
||
UserProfile,
|
||
WebhookConfig,
|
||
)
|
||
|
||
# Alembic Config object – provides access to values in alembic.ini.
|
||
config = context.config
|
||
|
||
# Set up Python logging from the config file (if present).
|
||
if config.config_file_name is not None:
|
||
fileConfig(config.config_file_name)
|
||
|
||
# MetaData object for autogenerate support.
|
||
target_metadata = Base.metadata
|
||
|
||
|
||
def _get_url() -> str:
|
||
"""Return the database URL, preferring the application config."""
|
||
url = config.get_main_option("sqlalchemy.url")
|
||
if url:
|
||
return url
|
||
# Fall back to application settings
|
||
from app.config import settings
|
||
|
||
return settings.database_url
|
||
|
||
|
||
def run_migrations_offline() -> None:
|
||
"""Run migrations in 'offline' mode.
|
||
|
||
Configures the context with just a URL and not an Engine.
|
||
Calls to ``context.execute()`` emit the given string to the script output.
|
||
"""
|
||
url = _get_url()
|
||
context.configure(
|
||
url=url,
|
||
target_metadata=target_metadata,
|
||
literal_binds=True,
|
||
dialect_opts={"paramstyle": "named"},
|
||
)
|
||
|
||
with context.begin_transaction():
|
||
context.run_migrations()
|
||
|
||
|
||
def run_migrations_online() -> None:
|
||
"""Run migrations in 'online' mode.
|
||
|
||
Creates an Engine (or reuses a connection passed via
|
||
``config.attributes["connection"]``) and associates it with the context.
|
||
"""
|
||
# If a connection was passed programmatically, reuse it.
|
||
connectable = config.attributes.get("connection", None)
|
||
|
||
if connectable is not None:
|
||
# Already have a connection — run migrations directly.
|
||
context.configure(connection=connectable, target_metadata=target_metadata)
|
||
with context.begin_transaction():
|
||
context.run_migrations()
|
||
else:
|
||
# Create a new engine from configuration.
|
||
configuration = config.get_section(config.config_ini_section, {})
|
||
url = _get_url()
|
||
if url:
|
||
configuration["sqlalchemy.url"] = url
|
||
connectable = engine_from_config(
|
||
configuration,
|
||
prefix="sqlalchemy.",
|
||
poolclass=pool.NullPool,
|
||
)
|
||
|
||
with connectable.connect() as connection:
|
||
context.configure(connection=connection, target_metadata=target_metadata)
|
||
with context.begin_transaction():
|
||
context.run_migrations()
|
||
|
||
|
||
if context.is_offline_mode():
|
||
run_migrations_offline()
|
||
else:
|
||
run_migrations_online()
|