"""empty message Revision ID: 5d99e6d4cdc6 Revises: 003 Create Date: 2026-01-16 15:31:36.288933 """ from alembic import op import sqlalchemy as sa # revision identifiers, used by Alembic. revision = '004' down_revision = '003' branch_labels = None depends_on = None def upgrade(): # ### commands auto generated by Alembic - please adjust! ### op.create_table('mfa_policy_compliance', sa.Column('user_id', sa.String(length=36), nullable=False), sa.Column('organization_id', sa.String(length=36), nullable=False), sa.Column('status', sa.Enum('NOT_APPLICABLE', 'PENDING', 'IN_GRACE', 'COMPLIANT', 'PAST_DUE', 'SUSPENDED', name='mfacompliancestatus'), nullable=False), sa.Column('policy_version', sa.Integer(), nullable=False), sa.Column('applied_at', sa.DateTime(), nullable=True), sa.Column('deadline_at', sa.DateTime(), nullable=True), sa.Column('compliant_at', sa.DateTime(), nullable=True), sa.Column('suspended_at', sa.DateTime(), nullable=True), sa.Column('last_notified_at', sa.DateTime(), nullable=True), sa.Column('notification_count', sa.Integer(), nullable=False), sa.Column('id', sa.String(length=36), nullable=False), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.Column('deleted_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['organization_id'], ['organizations.id'], ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('id'), sa.UniqueConstraint('user_id', 'organization_id', name='uix_user_org_compliance') ) op.create_index(op.f('ix_mfa_policy_compliance_organization_id'), 'mfa_policy_compliance', ['organization_id'], unique=False) op.create_index(op.f('ix_mfa_policy_compliance_user_id'), 'mfa_policy_compliance', ['user_id'], unique=False) op.create_table('organization_security_policies', sa.Column('organization_id', sa.String(length=36), nullable=False), sa.Column('mfa_policy_mode', sa.Enum('DISABLED', 'OPTIONAL', 'REQUIRE_TOTP', 'REQUIRE_WEBAUTHN', 'REQUIRE_TOTP_OR_WEBAUTHN', name='mfapolicymode'), nullable=False), sa.Column('mfa_grace_period_days', sa.Integer(), nullable=False), sa.Column('notify_days_before', sa.Integer(), nullable=False), sa.Column('policy_version', sa.Integer(), nullable=False), sa.Column('updated_by_user_id', sa.String(length=36), nullable=True), sa.Column('id', sa.String(length=36), nullable=False), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.Column('deleted_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['organization_id'], ['organizations.id'], ), sa.ForeignKeyConstraint(['updated_by_user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('id') ) op.create_index(op.f('ix_organization_security_policies_organization_id'), 'organization_security_policies', ['organization_id'], unique=True) op.create_table('user_security_policies', sa.Column('user_id', sa.String(length=36), nullable=False), sa.Column('organization_id', sa.String(length=36), nullable=False), sa.Column('mfa_override_mode', sa.Enum('INHERIT', 'REQUIRED', 'EXEMPT', name='mfarequirementoverride'), nullable=False), sa.Column('force_totp', sa.Boolean(), nullable=False), sa.Column('force_webauthn', sa.Boolean(), nullable=False), sa.Column('id', sa.String(length=36), nullable=False), sa.Column('created_at', sa.DateTime(), nullable=False), sa.Column('updated_at', sa.DateTime(), nullable=False), sa.Column('deleted_at', sa.DateTime(), nullable=True), sa.ForeignKeyConstraint(['organization_id'], ['organizations.id'], ), sa.ForeignKeyConstraint(['user_id'], ['users.id'], ), sa.PrimaryKeyConstraint('id'), sa.UniqueConstraint('id'), sa.UniqueConstraint('user_id', 'organization_id', name='uix_user_org_policy') ) op.create_index(op.f('ix_user_security_policies_organization_id'), 'user_security_policies', ['organization_id'], unique=False) op.create_index(op.f('ix_user_security_policies_user_id'), 'user_security_policies', ['user_id'], unique=False) # Use batch operations for SQLite-compatible column type changes with op.batch_alter_table('audit_logs', schema=None) as batch_op: batch_op.alter_column('action', existing_type=sa.VARCHAR(length=22), type_=sa.Enum('USER_LOGIN', 'USER_LOGOUT', 'USER_REGISTER', 'USER_UPDATE', 'USER_DELETE', 'PASSWORD_CHANGE', 'PASSWORD_RESET', 'ORG_CREATE', 'ORG_UPDATE', 'ORG_DELETE', 'ORG_MEMBER_ADD', 'ORG_MEMBER_REMOVE', 'ORG_MEMBER_ROLE_CHANGE', 'SESSION_CREATE', 'SESSION_REVOKE', 'AUTH_METHOD_ADD', 'AUTH_METHOD_REMOVE', 'TOTP_ENROLL_INITIATED', 'TOTP_ENROLL_COMPLETED', 'TOTP_VERIFY_SUCCESS', 'TOTP_VERIFY_FAILED', 'TOTP_DISABLED', 'TOTP_BACKUP_CODE_USED', 'TOTP_BACKUP_CODES_REGENERATED', 'WEBAUTHN_REGISTER_INITIATED', 'WEBAUTHN_REGISTER_COMPLETED', 'WEBAUTHN_REGISTER_FAILED', 'WEBAUTHN_LOGIN_INITIATED', 'WEBAUTHN_LOGIN_SUCCESS', 'WEBAUTHN_LOGIN_FAILED', 'WEBAUTHN_CREDENTIAL_DELETED', 'WEBAUTHN_CREDENTIAL_RENAMED', 'ORG_SECURITY_POLICY_UPDATE', 'USER_SECURITY_POLICY_OVERRIDE_UPDATE', 'MFA_POLICY_USER_SUSPENDED', 'MFA_POLICY_USER_COMPLIANT', name='auditaction'), existing_nullable=False) op.drop_index(op.f('ix_oidc_jwks_keys_is_active'), table_name='oidc_jwks_keys') op.add_column('sessions', sa.Column('is_compliance_only', sa.Boolean(), nullable=False)) with op.batch_alter_table('users', schema=None) as batch_op: batch_op.alter_column('status', existing_type=sa.VARCHAR(length=9), type_=sa.Enum('ACTIVE', 'INACTIVE', 'SUSPENDED', 'PENDING', 'COMPLIANCE_SUSPENDED', name='userstatus'), existing_nullable=False) # ### end Alembic commands ### def downgrade(): # ### commands auto generated by Alembic - please adjust! ### with op.batch_alter_table('users', schema=None) as batch_op: batch_op.alter_column('status', existing_type=sa.Enum('ACTIVE', 'INACTIVE', 'SUSPENDED', 'PENDING', 'COMPLIANCE_SUSPENDED', name='userstatus'), type_=sa.VARCHAR(length=9), existing_nullable=False) op.drop_column('sessions', 'is_compliance_only') op.create_index(op.f('ix_oidc_jwks_keys_is_active'), 'oidc_jwks_keys', ['is_active'], unique=False) with op.batch_alter_table('audit_logs', schema=None) as batch_op: batch_op.alter_column('action', existing_type=sa.Enum('USER_LOGIN', 'USER_LOGOUT', 'USER_REGISTER', 'USER_UPDATE', 'USER_DELETE', 'PASSWORD_CHANGE', 'PASSWORD_RESET', 'ORG_CREATE', 'ORG_UPDATE', 'ORG_DELETE', 'ORG_MEMBER_ADD', 'ORG_MEMBER_REMOVE', 'ORG_MEMBER_ROLE_CHANGE', 'SESSION_CREATE', 'SESSION_REVOKE', 'AUTH_METHOD_ADD', 'AUTH_METHOD_REMOVE', 'TOTP_ENROLL_INITIATED', 'TOTP_ENROLL_COMPLETED', 'TOTP_VERIFY_SUCCESS', 'TOTP_VERIFY_FAILED', 'TOTP_DISABLED', 'TOTP_BACKUP_CODE_USED', 'TOTP_BACKUP_CODES_REGENERATED', 'WEBAUTHN_REGISTER_INITIATED', 'WEBAUTHN_REGISTER_COMPLETED', 'WEBAUTHN_REGISTER_FAILED', 'WEBAUTHN_LOGIN_INITIATED', 'WEBAUTHN_LOGIN_SUCCESS', 'WEBAUTHN_LOGIN_FAILED', 'WEBAUTHN_CREDENTIAL_DELETED', 'WEBAUTHN_CREDENTIAL_RENAMED', 'ORG_SECURITY_POLICY_UPDATE', 'USER_SECURITY_POLICY_OVERRIDE_UPDATE', 'MFA_POLICY_USER_SUSPENDED', 'MFA_POLICY_USER_COMPLIANT', name='auditaction'), type_=sa.VARCHAR(length=22), existing_nullable=False) op.drop_index(op.f('ix_user_security_policies_user_id'), table_name='user_security_policies') op.drop_index(op.f('ix_user_security_policies_organization_id'), table_name='user_security_policies') op.drop_table('user_security_policies') op.drop_index(op.f('ix_organization_security_policies_organization_id'), table_name='organization_security_policies') op.drop_table('organization_security_policies') op.drop_index(op.f('ix_mfa_policy_compliance_user_id'), table_name='mfa_policy_compliance') op.drop_index(op.f('ix_mfa_policy_compliance_organization_id'), table_name='mfa_policy_compliance') op.drop_table('mfa_policy_compliance') # ### end Alembic commands ###