Refactor bw_ui_users table migration to conditionally drop columns and set username as primary key

This commit is contained in:
Théophile Diot 2025-01-10 11:35:00 +01:00
parent 27ac97828e
commit 5599cc8013
No known key found for this signature in database
GPG key ID: FA995104A0BA376A
6 changed files with 125 additions and 35 deletions

View file

@ -57,8 +57,10 @@ def upgrade() -> None:
existing_nullable=False,
)
# Drop bw_ui_users.id column
op.drop_column("bw_ui_users", "id")
# Drop bw_ui_users.id column if it exists
with op.batch_alter_table("bw_ui_users") as batch_op:
if "id" in [c["name"] for c in batch_op.impl.dialect.get_columns(op.get_bind(), "bw_ui_users")]:
batch_op.drop_column("id")
# Add the new order column to bw_template_settings
op.add_column("bw_template_settings", sa.Column("order", sa.Integer(), nullable=False))
@ -111,9 +113,6 @@ def downgrade() -> None:
existing_nullable=False,
)
# Re-add bw_ui_users.id and index on username
op.add_column("bw_ui_users", sa.Column("id", sa.Integer(), autoincrement=True, nullable=False))
# Drop the order column from bw_template_settings
op.drop_column("bw_template_settings", "order")

View file

@ -194,14 +194,21 @@ def upgrade():
# bw_ui_users changes
with op.batch_alter_table("bw_ui_users") as batch_op:
# Drop existing primary key and columns
batch_op.drop_column("id")
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
# Add new columns
batch_op.add_column(sa.Column("email", sa.String(256), nullable=True, unique=True))
batch_op.add_column(sa.Column("admin", sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column("theme", sa.Enum("light", "dark", name="themes_enum"), nullable=False, server_default="light"))
batch_op.add_column(sa.Column("totp_secret", sa.String(256), nullable=True))
batch_op.add_column(sa.Column("creation_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
batch_op.add_column(sa.Column("update_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
# Make username the primary key
batch_op.alter_column("username", existing_type=sa.String(256), nullable=False, primary_key=True)
# Set defaults for existing bw_ui_users rows
op.execute("UPDATE bw_ui_users SET admin=1, theme='light', creation_date=CURRENT_TIMESTAMP, update_date=CURRENT_TIMESTAMP")
@ -418,9 +425,12 @@ def downgrade():
batch_op.drop_column("totp_secret")
batch_op.drop_column("creation_date")
batch_op.drop_column("update_date")
batch_op.add_column(sa.Column("id", sa.Integer(), sa.Identity(start=1, increment=1), primary_key=True))
batch_op.add_column(sa.Column("is_two_factor_enabled", sa.Boolean, nullable=False, server_default="0"))
batch_op.add_column(sa.Column("secret_token", sa.String(32), nullable=True, unique=True, default=None))
batch_op.alter_column("username", existing_type=sa.String(256), nullable=False, primary_key=False)
# bw_plugin_pages revert: remove data, checksum, add template_file, template_checksum, actions_file, actions_checksum, obfuscation_file, obfuscation_checksum
with op.batch_alter_table("bw_plugin_pages") as batch_op:
batch_op.drop_column("data")

View file

@ -57,8 +57,10 @@ def upgrade() -> None:
existing_nullable=False,
)
# Drop bw_ui_users.id column
op.drop_column("bw_ui_users", "id")
# Drop bw_ui_users.id column if it exists
with op.batch_alter_table("bw_ui_users") as batch_op:
if "id" in [c["name"] for c in batch_op.impl.dialect.get_columns(op.get_bind(), "bw_ui_users")]:
batch_op.drop_column("id")
# Add the new order column to bw_template_settings
op.add_column("bw_template_settings", sa.Column("order", sa.Integer(), nullable=False))
@ -111,9 +113,6 @@ def downgrade() -> None:
existing_nullable=False,
)
# Re-add bw_ui_users.id and index on username
op.add_column("bw_ui_users", sa.Column("id", sa.Integer(), autoincrement=True, nullable=False))
# Drop the order column from bw_template_settings
op.drop_column("bw_template_settings", "order")

View file

@ -194,14 +194,21 @@ def upgrade():
# bw_ui_users changes
with op.batch_alter_table("bw_ui_users") as batch_op:
# Drop existing primary key and columns
batch_op.drop_column("id")
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
# Add new columns
batch_op.add_column(sa.Column("email", sa.String(256), nullable=True, unique=True))
batch_op.add_column(sa.Column("admin", sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column("theme", sa.Enum("light", "dark", name="themes_enum"), nullable=False, server_default="light"))
batch_op.add_column(sa.Column("totp_secret", sa.String(256), nullable=True))
batch_op.add_column(sa.Column("creation_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
batch_op.add_column(sa.Column("update_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
# Make username the primary key
batch_op.alter_column("username", existing_type=sa.String(256), nullable=False, primary_key=True)
# Set defaults for existing bw_ui_users rows
op.execute("UPDATE bw_ui_users SET admin=1, theme='light', creation_date=CURRENT_TIMESTAMP, update_date=CURRENT_TIMESTAMP")
@ -418,9 +425,12 @@ def downgrade():
batch_op.drop_column("totp_secret")
batch_op.drop_column("creation_date")
batch_op.drop_column("update_date")
batch_op.add_column(sa.Column("id", sa.Integer(), sa.Identity(start=1, increment=1), primary_key=True))
batch_op.add_column(sa.Column("is_two_factor_enabled", sa.Boolean, nullable=False, server_default="0"))
batch_op.add_column(sa.Column("secret_token", sa.String(32), nullable=True, unique=True, default=None))
batch_op.alter_column("username", existing_type=sa.String(256), nullable=False, primary_key=False)
# bw_plugin_pages revert: remove data, checksum, add template_file, template_checksum, actions_file, actions_checksum, obfuscation_file, obfuscation_checksum
with op.batch_alter_table("bw_plugin_pages") as batch_op:
batch_op.drop_column("data")

View file

@ -203,21 +203,28 @@ def upgrade():
op.execute("CREATE TYPE themes_enum AS ENUM ('light', 'dark')")
with op.batch_alter_table("bw_ui_users") as batch_op:
# Drop existing primary key and columns
batch_op.drop_column("id")
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
# Add new columns
batch_op.add_column(sa.Column("email", sa.String(256), nullable=True, unique=True))
batch_op.add_column(sa.Column("admin", sa.Boolean(), nullable=False, server_default="0"))
batch_op.add_column(sa.Column("theme", themes_enum, nullable=False, server_default="light"))
batch_op.add_column(sa.Column("totp_secret", sa.String(256), nullable=True))
batch_op.add_column(sa.Column("creation_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP")))
batch_op.add_column(sa.Column("update_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.text("CURRENT_TIMESTAMP")))
batch_op.drop_column("is_two_factor_enabled")
batch_op.drop_column("secret_token")
batch_op.add_column(sa.Column("creation_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
batch_op.add_column(sa.Column("update_date", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.current_timestamp()))
# Make username the primary key
batch_op.alter_column("username", existing_type=sa.String(256), nullable=False, primary_key=True)
op.execute("UPDATE bw_ui_users SET admin=TRUE, theme='light', creation_date=CURRENT_TIMESTAMP, update_date=CURRENT_TIMESTAMP")
# bw_plugin_pages changes
with op.batch_alter_table("bw_plugin_pages") as batch_op:
batch_op.add_column(sa.Column("data", sa.LargeBinary(length=(2**32) - 1), nullable=False))
batch_op.add_column(sa.Column("checksum", sa.String(128), nullable=False))
batch_op.add_column(sa.Column("data", sa.LargeBinary(length=(2**32) - 1), nullable=True))
batch_op.add_column(sa.Column("checksum", sa.String(128), nullable=True))
op.execute(
"""
@ -228,6 +235,8 @@ def upgrade():
)
with op.batch_alter_table("bw_plugin_pages") as batch_op:
batch_op.alter_column("data", existing_type=sa.LargeBinary(length=(2**32) - 1), nullable=False)
batch_op.alter_column("checksum", existing_type=sa.String(128), nullable=False)
batch_op.drop_column("template_file")
batch_op.drop_column("template_checksum")
batch_op.drop_column("actions_file")
@ -252,7 +261,7 @@ def upgrade():
with op.batch_alter_table("bw_instances") as batch_op:
batch_op.add_column(sa.Column("name", sa.String(256), nullable=True))
batch_op.add_column(sa.Column("type", new_it_enum, nullable=True))
batch_op.add_column(sa.Column("status", new_it_enum, nullable=True))
batch_op.add_column(sa.Column("status", new_is_enum, nullable=True))
batch_op.add_column(sa.Column("method", old_methods_enum_for_instances, nullable=True))
batch_op.add_column(sa.Column("creation_date", sa.DateTime(timezone=True), nullable=True, server_default=sa.text("CURRENT_TIMESTAMP")))
batch_op.add_column(sa.Column("last_seen", sa.DateTime(timezone=True), nullable=True, server_default=sa.text("CURRENT_TIMESTAMP")))

View file

@ -149,13 +149,19 @@ def upgrade() -> None:
# Update bw_instances.status from Enum("loading", "up", "down", name="instance_status_enum") to Enum("loading", "up", "down", "failover", name="instance_status_enum")
op.execute("ALTER TYPE instance_status_enum ADD VALUE 'failover'")
op.alter_column(
"bw_instances",
"status",
existing_type=postgresql.ENUM("loading", "up", "down", name="instance_status_enum", create_type=False),
type_=postgresql.ENUM("loading", "up", "down", "failover", name="instance_status_enum", create_type=False),
existing_nullable=False,
)
# Check if bw_instances.status has instance_type_enum type and replace it with instance_status_enum if needed
with op.batch_alter_table("bw_instances") as batch_op:
# Create temporary column with new enum type
batch_op.add_column(
sa.Column("status_new", postgresql.ENUM("loading", "up", "down", "failover", name="instance_status_enum", create_type=False), nullable=True)
)
# Copy data to new column
op.execute("UPDATE bw_instances SET status_new = status::text::instance_status_enum")
# Drop old column
batch_op.drop_column("status")
# Rename new column to status
batch_op.alter_column("status_new", new_column_name="status", nullable=False)
# Add the new order column to bw_template_settings
# Step 1: Add column as nullable
@ -177,6 +183,70 @@ def upgrade() -> None:
# Step 3: Alter column to NOT NULL
op.alter_column("bw_template_custom_configs", "order", nullable=False)
# First drop Identity properties
op.execute(
"""
ALTER TABLE bw_plugin_pages ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_jobs_cache ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_jobs_runs ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_custom_configs ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_cli_commands ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_template_settings ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_template_custom_configs ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_ui_user_recovery_codes ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_ui_user_sessions ALTER COLUMN id DROP IDENTITY IF EXISTS;
ALTER TABLE bw_ui_user_columns_preferences ALTER COLUMN id DROP IDENTITY IF EXISTS;
"""
)
# Create sequences
op.execute(
"""
CREATE SEQUENCE IF NOT EXISTS bw_plugin_pages_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_jobs_cache_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_jobs_runs_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_custom_configs_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_cli_commands_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_template_settings_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_template_custom_configs_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_ui_user_recovery_codes_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_ui_user_sessions_id_seq;
CREATE SEQUENCE IF NOT EXISTS bw_ui_user_columns_preferences_id_seq;
"""
)
# Set sequence values
op.execute(
"""
SELECT setval('bw_plugin_pages_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_plugin_pages));
SELECT setval('bw_jobs_cache_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_jobs_cache));
SELECT setval('bw_jobs_runs_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_jobs_runs));
SELECT setval('bw_custom_configs_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_custom_configs));
SELECT setval('bw_cli_commands_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_cli_commands));
SELECT setval('bw_template_settings_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_template_settings));
SELECT setval('bw_template_custom_configs_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_template_custom_configs));
SELECT setval('bw_ui_user_recovery_codes_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_ui_user_recovery_codes));
SELECT setval('bw_ui_user_sessions_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_ui_user_sessions));
SELECT setval('bw_ui_user_columns_preferences_id_seq', (SELECT COALESCE(MAX(id), 0) + 1 FROM bw_ui_user_columns_preferences));
"""
)
# Set column defaults
op.execute(
"""
ALTER TABLE bw_plugin_pages ALTER COLUMN id SET DEFAULT nextval('bw_plugin_pages_id_seq');
ALTER TABLE bw_jobs_cache ALTER COLUMN id SET DEFAULT nextval('bw_jobs_cache_id_seq');
ALTER TABLE bw_jobs_runs ALTER COLUMN id SET DEFAULT nextval('bw_jobs_runs_id_seq');
ALTER TABLE bw_custom_configs ALTER COLUMN id SET DEFAULT nextval('bw_custom_configs_id_seq');
ALTER TABLE bw_cli_commands ALTER COLUMN id SET DEFAULT nextval('bw_cli_commands_id_seq');
ALTER TABLE bw_template_settings ALTER COLUMN id SET DEFAULT nextval('bw_template_settings_id_seq');
ALTER TABLE bw_template_custom_configs ALTER COLUMN id SET DEFAULT nextval('bw_template_custom_configs_id_seq');
ALTER TABLE bw_ui_user_recovery_codes ALTER COLUMN id SET DEFAULT nextval('bw_ui_user_recovery_codes_id_seq');
ALTER TABLE bw_ui_user_sessions ALTER COLUMN id SET DEFAULT nextval('bw_ui_user_sessions_id_seq');
ALTER TABLE bw_ui_user_columns_preferences ALTER COLUMN id SET DEFAULT nextval('bw_ui_user_columns_preferences_id_seq');
"""
)
# Update the version in bw_metadata
op.execute("UPDATE bw_metadata SET version = '1.6.0-rc1' WHERE id = 1")
@ -315,13 +385,6 @@ def downgrade() -> None:
# Update bw_instances.status from Enum("loading", "up", "down", "failover", name="instance_status_enum") to Enum("loading", "up", "down", name="instance_status_enum")
op.execute("ALTER TYPE instance_status_enum DROP VALUE 'failover'")
op.alter_column(
"bw_instances",
"status",
existing_type=postgresql.ENUM("loading", "up", "down", "failover", name="instance_status_enum", create_type=False),
type_=postgresql.ENUM("loading", "up", "down", name="instance_status_enum", create_type=False),
existing_nullable=False,
)
# Drop 'order' column from 'bw_template_settings'
with op.batch_alter_table("bw_template_settings") as batch_op: