fix: RLS seeding, FQDN 422, stale migration hash, mail_accounts.password_salt
- Use migration engine (crm_migration, BYPASSRLS) for default data seeding in app/main.py instead of crm_api role which is RLS-enforced - Skip domains PATCH for dockercompose apps in deploy_api() to avoid 422 - Regenerate migration_hashes.txt for 0085_restore_tenant_rls.py - Add migration 0110: password_salt column to mail_accounts
This commit is contained in:
@@ -83,7 +83,7 @@ ba5b221f7ce0271a1b531eb441d2f0afe7b3d53bd44e602b8e839a3806059bfb 0081_disable_r
|
|||||||
1705c1788ea57085c2ffe99d985e077ffa2e2e45482a5b6af162a76dcbeda34c 0082_add_sensitivity_to_custom_field_definitions.py
|
1705c1788ea57085c2ffe99d985e077ffa2e2e45482a5b6af162a76dcbeda34c 0082_add_sensitivity_to_custom_field_definitions.py
|
||||||
f8409a0e4952703b5a1a1ba064f8622071f12c657ad4e8ff1a09c2020d768762 0083_add_missing_deleted_at_columns.py
|
f8409a0e4952703b5a1a1ba064f8622071f12c657ad4e8ff1a09c2020d768762 0083_add_missing_deleted_at_columns.py
|
||||||
d2bdad015bdf16f6c911f58a08103b1814f0f6d987b4ecd290732ee7a185a843 0084_rls_fail_closed_reactivate.py
|
d2bdad015bdf16f6c911f58a08103b1814f0f6d987b4ecd290732ee7a185a843 0084_rls_fail_closed_reactivate.py
|
||||||
9d398d6997302ab5bc045bd655fdfba08fd617b087b86dd2a02356254244570e 0085_restore_tenant_rls.py
|
b66e11bbcb52d7cfde518cde523a4d8808ddb4a62cc3b8c39aec3c58b95abe19 0085_restore_tenant_rls.py
|
||||||
b184eab067c0dfaa66712bd74471b4c65715e90a07521b17577ed15bac707259 0086_fix_global_tables_force_rls.py
|
b184eab067c0dfaa66712bd74471b4c65715e90a07521b17577ed15bac707259 0086_fix_global_tables_force_rls.py
|
||||||
f0f33e314b52a849f1bad06cfa9ffb5da07890764bc8d22dcd43237293ed90db 0087_add_timestamps_to_password_reset_tokens.py
|
f0f33e314b52a849f1bad06cfa9ffb5da07890764bc8d22dcd43237293ed90db 0087_add_timestamps_to_password_reset_tokens.py
|
||||||
38e3f4454e079faed2e6fc78cec632d6f78189c46750a7668a9c9c1a845f2bd4 0088_auth_rls_policies.py
|
38e3f4454e079faed2e6fc78cec632d6f78189c46750a7668a9c9c1a845f2bd4 0088_auth_rls_policies.py
|
||||||
|
|||||||
@@ -0,0 +1,39 @@
|
|||||||
|
"""Add password_salt column to mail_accounts.
|
||||||
|
|
||||||
|
⚠️ KI / AGENT HINWEIS — BITTE VOR ÄNDERUNGEN LESEN ⚠️
|
||||||
|
|
||||||
|
Das ORM-Model MailAccount (app/plugins/builtins/mail/models.py) referenziert
|
||||||
|
die Spalte `password_salt` (String(64), nullable=False, default="").
|
||||||
|
In der Produktions-DB fehlt diese Spalte, was zu SQLAlchemy-Fehlern führt
|
||||||
|
beim Lesen oder Schreiben von MailAccount-Datensätzen.
|
||||||
|
|
||||||
|
Diese Migration fügt die Spalte mit ADD COLUMN IF NOT EXISTS hinzu, sodass
|
||||||
|
bestehende Datensätze den Default-Wert "" (leerer String) erhalten.
|
||||||
|
|
||||||
|
Revision ID: 0110
|
||||||
|
Revises: 0109
|
||||||
|
"""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
from alembic import op
|
||||||
|
import sqlalchemy as sa
|
||||||
|
|
||||||
|
revision = "0110"
|
||||||
|
down_revision = "0109"
|
||||||
|
branch_labels = None
|
||||||
|
depends_on = None
|
||||||
|
|
||||||
|
|
||||||
|
def upgrade() -> None:
|
||||||
|
op.execute(
|
||||||
|
"ALTER TABLE mail_accounts "
|
||||||
|
"ADD COLUMN IF NOT EXISTS password_salt VARCHAR(64) NOT NULL DEFAULT ''"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def downgrade() -> None:
|
||||||
|
op.execute(
|
||||||
|
"ALTER TABLE mail_accounts "
|
||||||
|
"DROP COLUMN IF EXISTS password_salt"
|
||||||
|
)
|
||||||
+5
-1
@@ -287,9 +287,13 @@ async def lifespan(app: FastAPI):
|
|||||||
logger.info("Field definitions registered for %d active plugins", len(active_plugin_names))
|
logger.info("Field definitions registered for %d active plugins", len(active_plugin_names))
|
||||||
|
|
||||||
# Seed default data (EUR currency, 19%/7% tax rates) for all tenants
|
# Seed default data (EUR currency, 19%/7% tax rates) for all tenants
|
||||||
|
# ⚠️ Use migration engine (crm_migration, BYPASSRLS) — RLS on currencies/taxes
|
||||||
|
# blocks inserts from crm_api role without tenant context.
|
||||||
from app.core.seeds import seed_default_data
|
from app.core.seeds import seed_default_data
|
||||||
|
from app.core.db import get_migration_session_factory
|
||||||
|
|
||||||
async with async_session() as db:
|
mig_session_factory = get_migration_session_factory()
|
||||||
|
async with mig_session_factory() as db:
|
||||||
try:
|
try:
|
||||||
await seed_default_data(db)
|
await seed_default_data(db)
|
||||||
await db.commit()
|
await db.commit()
|
||||||
|
|||||||
+16
-4
@@ -307,13 +307,25 @@ def ssh_run(cmd: str, timeout: int = 60) -> tuple[int, str]:
|
|||||||
def deploy_api(client: CoolifyClient, app_uuid: str, skip_build: bool = False) -> StepResult:
|
def deploy_api(client: CoolifyClient, app_uuid: str, skip_build: bool = False) -> StepResult:
|
||||||
"""Deploy or restart the application via Coolify API.
|
"""Deploy or restart the application via Coolify API.
|
||||||
Uses /api/v1/deploy which works for both dockerfile and dockercompose build packs."""
|
Uses /api/v1/deploy which works for both dockerfile and dockercompose build packs."""
|
||||||
# Set FQDN via PATCH
|
# Set FQDN via PATCH — only for non-dockercompose apps.
|
||||||
|
# dockercompose apps use docker_compose_domains, not domains.
|
||||||
|
# PATCHing domains on a dockercompose app returns 422.
|
||||||
if APP_DOMAIN:
|
if APP_DOMAIN:
|
||||||
print(f" Setting FQDN to {APP_DOMAIN}...")
|
|
||||||
try:
|
try:
|
||||||
client.update_application(app_uuid, domains=APP_DOMAIN)
|
app_info = client.get_application(app_uuid)
|
||||||
|
build_pack = app_info.get("build_pack", "")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f" Warning: could not set FQDN: {e}")
|
print(f" Warning: could not fetch app info to check build_pack: {e}")
|
||||||
|
build_pack = ""
|
||||||
|
|
||||||
|
if build_pack == "dockercompose":
|
||||||
|
print(f" Skipping FQDN PATCH (dockercompose app — domain set via docker_compose_domains)")
|
||||||
|
else:
|
||||||
|
print(f" Setting FQDN to {APP_DOMAIN}...")
|
||||||
|
try:
|
||||||
|
client.update_application(app_uuid, domains=APP_DOMAIN)
|
||||||
|
except Exception as e:
|
||||||
|
print(f" Warning: could not set FQDN: {e}")
|
||||||
|
|
||||||
print(" Triggering Coolify deploy via /api/v1/deploy...")
|
print(" Triggering Coolify deploy via /api/v1/deploy...")
|
||||||
try:
|
try:
|
||||||
|
|||||||
Reference in New Issue
Block a user