mirror of
https://github.com/DRYTRIX/TimeTracker.git
synced 2026-01-14 07:50:18 -06:00
fix: make migration 081 tolerant of existing settings columns
Some legacy/partially-upgraded databases already have one or more integration OAuth columns in settings (e.g. google_calendar_client_id). Only add missing columns and set defaults for columns that exist so upgrades don't fail with DuplicateColumn. Bump version to 4.8.12.
This commit is contained in:
@@ -25,90 +25,159 @@ branch_labels = None
|
||||
depends_on = None
|
||||
|
||||
|
||||
def _has_table(inspector, table_name: str) -> bool:
|
||||
try:
|
||||
return table_name in inspector.get_table_names()
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _has_column(inspector, table_name: str, column_name: str) -> bool:
|
||||
try:
|
||||
return column_name in {c["name"] for c in inspector.get_columns(table_name)}
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def upgrade():
|
||||
"""Add integration OAuth credential columns to settings table"""
|
||||
bind = op.get_bind()
|
||||
inspector = sa.inspect(bind)
|
||||
|
||||
if not _has_table(inspector, "settings"):
|
||||
return
|
||||
|
||||
settings_cols = {c["name"] for c in inspector.get_columns("settings")}
|
||||
|
||||
with op.batch_alter_table('settings', schema=None) as batch_op:
|
||||
# Google Calendar
|
||||
batch_op.add_column(sa.Column('google_calendar_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('google_calendar_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'google_calendar_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('google_calendar_client_id', sa.String(length=255), nullable=True))
|
||||
if 'google_calendar_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('google_calendar_client_secret', sa.String(length=255), nullable=True))
|
||||
|
||||
# Outlook Calendar
|
||||
batch_op.add_column(sa.Column('outlook_calendar_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('outlook_calendar_client_secret', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('outlook_calendar_tenant_id', sa.String(length=255), nullable=True))
|
||||
if 'outlook_calendar_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('outlook_calendar_client_id', sa.String(length=255), nullable=True))
|
||||
if 'outlook_calendar_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('outlook_calendar_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'outlook_calendar_tenant_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('outlook_calendar_tenant_id', sa.String(length=255), nullable=True))
|
||||
|
||||
# Microsoft Teams
|
||||
batch_op.add_column(sa.Column('microsoft_teams_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('microsoft_teams_client_secret', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('microsoft_teams_tenant_id', sa.String(length=255), nullable=True))
|
||||
if 'microsoft_teams_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('microsoft_teams_client_id', sa.String(length=255), nullable=True))
|
||||
if 'microsoft_teams_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('microsoft_teams_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'microsoft_teams_tenant_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('microsoft_teams_tenant_id', sa.String(length=255), nullable=True))
|
||||
|
||||
# Asana
|
||||
batch_op.add_column(sa.Column('asana_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('asana_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'asana_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('asana_client_id', sa.String(length=255), nullable=True))
|
||||
if 'asana_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('asana_client_secret', sa.String(length=255), nullable=True))
|
||||
|
||||
# Trello
|
||||
batch_op.add_column(sa.Column('trello_api_key', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('trello_api_secret', sa.String(length=255), nullable=True))
|
||||
if 'trello_api_key' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('trello_api_key', sa.String(length=255), nullable=True))
|
||||
if 'trello_api_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('trello_api_secret', sa.String(length=255), nullable=True))
|
||||
|
||||
# GitLab
|
||||
batch_op.add_column(sa.Column('gitlab_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('gitlab_client_secret', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('gitlab_instance_url', sa.String(length=500), nullable=True))
|
||||
if 'gitlab_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('gitlab_client_id', sa.String(length=255), nullable=True))
|
||||
if 'gitlab_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('gitlab_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'gitlab_instance_url' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('gitlab_instance_url', sa.String(length=500), nullable=True))
|
||||
|
||||
# QuickBooks
|
||||
batch_op.add_column(sa.Column('quickbooks_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('quickbooks_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'quickbooks_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('quickbooks_client_id', sa.String(length=255), nullable=True))
|
||||
if 'quickbooks_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('quickbooks_client_secret', sa.String(length=255), nullable=True))
|
||||
|
||||
# Xero
|
||||
batch_op.add_column(sa.Column('xero_client_id', sa.String(length=255), nullable=True))
|
||||
batch_op.add_column(sa.Column('xero_client_secret', sa.String(length=255), nullable=True))
|
||||
if 'xero_client_id' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('xero_client_id', sa.String(length=255), nullable=True))
|
||||
if 'xero_client_secret' not in settings_cols:
|
||||
batch_op.add_column(sa.Column('xero_client_secret', sa.String(length=255), nullable=True))
|
||||
|
||||
# Set default empty values for existing rows
|
||||
op.execute("""
|
||||
UPDATE settings
|
||||
SET google_calendar_client_id = '',
|
||||
google_calendar_client_secret = '',
|
||||
outlook_calendar_client_id = '',
|
||||
outlook_calendar_client_secret = '',
|
||||
outlook_calendar_tenant_id = '',
|
||||
microsoft_teams_client_id = '',
|
||||
microsoft_teams_client_secret = '',
|
||||
microsoft_teams_tenant_id = '',
|
||||
asana_client_id = '',
|
||||
asana_client_secret = '',
|
||||
trello_api_key = '',
|
||||
trello_api_secret = '',
|
||||
gitlab_client_id = '',
|
||||
gitlab_client_secret = '',
|
||||
gitlab_instance_url = '',
|
||||
quickbooks_client_id = '',
|
||||
quickbooks_client_secret = '',
|
||||
xero_client_id = '',
|
||||
xero_client_secret = ''
|
||||
WHERE google_calendar_client_id IS NULL
|
||||
""")
|
||||
# Refresh column list after alterations, then set defaults only for columns that exist.
|
||||
inspector = sa.inspect(op.get_bind())
|
||||
settings_cols = {c["name"] for c in inspector.get_columns("settings")}
|
||||
|
||||
set_parts = []
|
||||
for col in [
|
||||
"google_calendar_client_id",
|
||||
"google_calendar_client_secret",
|
||||
"outlook_calendar_client_id",
|
||||
"outlook_calendar_client_secret",
|
||||
"outlook_calendar_tenant_id",
|
||||
"microsoft_teams_client_id",
|
||||
"microsoft_teams_client_secret",
|
||||
"microsoft_teams_tenant_id",
|
||||
"asana_client_id",
|
||||
"asana_client_secret",
|
||||
"trello_api_key",
|
||||
"trello_api_secret",
|
||||
"gitlab_client_id",
|
||||
"gitlab_client_secret",
|
||||
"gitlab_instance_url",
|
||||
"quickbooks_client_id",
|
||||
"quickbooks_client_secret",
|
||||
"xero_client_id",
|
||||
"xero_client_secret",
|
||||
]:
|
||||
if col in settings_cols:
|
||||
set_parts.append(f"{col} = ''")
|
||||
|
||||
if set_parts:
|
||||
where_col = (
|
||||
"google_calendar_client_id"
|
||||
if "google_calendar_client_id" in settings_cols
|
||||
else set_parts[0].split(" = ")[0]
|
||||
)
|
||||
op.execute(
|
||||
f"UPDATE settings SET {', '.join(set_parts)} WHERE {where_col} IS NULL"
|
||||
)
|
||||
|
||||
|
||||
def downgrade():
|
||||
"""Remove integration credential columns from settings table"""
|
||||
with op.batch_alter_table('settings', schema=None) as batch_op:
|
||||
batch_op.drop_column('xero_client_secret')
|
||||
batch_op.drop_column('xero_client_id')
|
||||
batch_op.drop_column('quickbooks_client_secret')
|
||||
batch_op.drop_column('quickbooks_client_id')
|
||||
batch_op.drop_column('gitlab_instance_url')
|
||||
batch_op.drop_column('gitlab_client_secret')
|
||||
batch_op.drop_column('gitlab_client_id')
|
||||
batch_op.drop_column('trello_api_secret')
|
||||
batch_op.drop_column('trello_api_key')
|
||||
batch_op.drop_column('asana_client_secret')
|
||||
batch_op.drop_column('asana_client_id')
|
||||
batch_op.drop_column('microsoft_teams_tenant_id')
|
||||
batch_op.drop_column('microsoft_teams_client_secret')
|
||||
batch_op.drop_column('microsoft_teams_client_id')
|
||||
batch_op.drop_column('outlook_calendar_tenant_id')
|
||||
batch_op.drop_column('outlook_calendar_client_secret')
|
||||
batch_op.drop_column('outlook_calendar_client_id')
|
||||
batch_op.drop_column('google_calendar_client_secret')
|
||||
batch_op.drop_column('google_calendar_client_id')
|
||||
bind = op.get_bind()
|
||||
inspector = sa.inspect(bind)
|
||||
if not _has_table(inspector, "settings"):
|
||||
return
|
||||
|
||||
settings_cols = {c["name"] for c in inspector.get_columns("settings")}
|
||||
|
||||
with op.batch_alter_table('settings', schema=None) as batch_op:
|
||||
for col in [
|
||||
'xero_client_secret',
|
||||
'xero_client_id',
|
||||
'quickbooks_client_secret',
|
||||
'quickbooks_client_id',
|
||||
'gitlab_instance_url',
|
||||
'gitlab_client_secret',
|
||||
'gitlab_client_id',
|
||||
'trello_api_secret',
|
||||
'trello_api_key',
|
||||
'asana_client_secret',
|
||||
'asana_client_id',
|
||||
'microsoft_teams_tenant_id',
|
||||
'microsoft_teams_client_secret',
|
||||
'microsoft_teams_client_id',
|
||||
'outlook_calendar_tenant_id',
|
||||
'outlook_calendar_client_secret',
|
||||
'outlook_calendar_client_id',
|
||||
'google_calendar_client_secret',
|
||||
'google_calendar_client_id',
|
||||
]:
|
||||
if col in settings_cols:
|
||||
try:
|
||||
batch_op.drop_column(col)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user