fix: add is_admin column migration + additive safety net
Alembic migration 86c7b1d6a710 adds is_admin BOOLEAN DEFAULT FALSE to the roles table. Fixes login crash after M-3 change: psycopg2.errors.UndefinedColumn: column roles.is_admin does not exist Also adds _ensure_roles_is_admin_column() as an additive migration safety net for environments that don't run alembic automatically. To apply: cd backend && source .venv/bin/activate && alembic upgrade head
This commit is contained in:
@@ -8,6 +8,7 @@ ENCRYPTION_KEY=change-me-to-a-fernet-key
|
||||
DATABASE_URL=postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools
|
||||
AUTH_DATABASE_URL=postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools
|
||||
TASKS_DATABASE_URL=postgresql+psycopg2://postgres:postgres@localhost:5432/ss_tools
|
||||
# Run after pulling: cd backend && source .venv/bin/activate && alembic upgrade head
|
||||
|
||||
# ── Optional ──
|
||||
ALLOWED_ORIGINS=http://localhost:5173
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
"""add is_admin column to roles table
|
||||
|
||||
Revision ID: 86c7b1d6a710
|
||||
Revises: b0c1d2e3f4a5
|
||||
Create Date: 2026-05-26 15:27:06.159151
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '86c7b1d6a710'
|
||||
down_revision: Union[str, Sequence[str], None] = 'b0c1d2e3f4a5'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
"""Add is_admin column to roles table."""
|
||||
op.add_column("roles", sa.Column("is_admin", sa.Boolean(), nullable=False, server_default=sa.text("false")))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
"""Remove is_admin column from roles table."""
|
||||
op.drop_column("roles", "is_admin")
|
||||
@@ -364,6 +364,41 @@ def _ensure_auth_users_columns(bind_engine):
|
||||
# #endregion _ensure_auth_users_columns
|
||||
|
||||
|
||||
# #region _ensure_roles_is_admin_column [C:3] [TYPE Function]
|
||||
# @BRIEF Add is_admin column to roles table if missing (additive migration).
|
||||
# @PRE Database connection is active.
|
||||
# @POST roles.is_admin column exists (BOOLEAN, default FALSE).
|
||||
# @SIDE_EFFECT Executes ALTER TABLE on the auth database.
|
||||
def _ensure_roles_is_admin_column(bind_engine):
|
||||
with belief_scope("_ensure_roles_is_admin_column"):
|
||||
table_name = "roles"
|
||||
inspector = inspect(bind_engine)
|
||||
if table_name not in inspector.get_table_names():
|
||||
return
|
||||
|
||||
existing_columns = {
|
||||
str(column.get("name") or "").strip()
|
||||
for column in inspector.get_columns(table_name)
|
||||
}
|
||||
|
||||
if "is_admin" in existing_columns:
|
||||
logger.reason("roles.is_admin column already exists")
|
||||
return
|
||||
|
||||
alter = "ALTER TABLE roles ADD COLUMN is_admin BOOLEAN NOT NULL DEFAULT FALSE"
|
||||
try:
|
||||
with bind_engine.begin() as connection:
|
||||
connection.execute(text(alter))
|
||||
logger.reason("Added roles.is_admin column", extra={"statement": alter})
|
||||
except Exception as migration_error:
|
||||
logger.explore(
|
||||
"roles.is_admin additive migration failed",
|
||||
extra={"error": str(migration_error)},
|
||||
)
|
||||
raise
|
||||
# #endregion _ensure_roles_is_admin_column
|
||||
|
||||
|
||||
# #region _ensure_filter_source_enum_values [C:3] [TYPE Function]
|
||||
# @BRIEF Adds missing FilterSource enum values to the PostgreSQL native filtersource type.
|
||||
# @PRE bind_engine points to application database with imported_filters table.
|
||||
|
||||
Reference in New Issue
Block a user