37 lines
1.2 KiB
Python
37 lines
1.2 KiB
Python
"""apitokens.resourcescopes: pin a service token to specific resource scopes.
|
|
|
|
A geenforce.fetch token handed to a fleet (e.g. displays) should reach only its
|
|
own manifest scope(s) and the blobs those scopes ship, not every scope by name
|
|
or every blob by hash. This nullable JSON column carries that allowlist; NULL =
|
|
unrestricted, so every existing token keeps working unchanged. Idempotent.
|
|
"""
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
# revision identifiers, used by Alembic.
|
|
revision = '7d30_apitoken_resourcescopes'
|
|
down_revision = '7d29_supportteam_webhookurl'
|
|
branch_labels = None
|
|
depends_on = None
|
|
|
|
|
|
def _has_column(bind, table, column):
|
|
inspector = sa.inspect(bind)
|
|
if table not in inspector.get_table_names():
|
|
return False
|
|
return column in {c['name'] for c in inspector.get_columns(table)}
|
|
|
|
|
|
def upgrade():
|
|
bind = op.get_bind()
|
|
if not _has_column(bind, 'apitokens', 'resourcescopes'):
|
|
op.add_column('apitokens',
|
|
sa.Column('resourcescopes', sa.Text(), nullable=True))
|
|
|
|
|
|
def downgrade():
|
|
bind = op.get_bind()
|
|
if _has_column(bind, 'apitokens', 'resourcescopes'):
|
|
op.drop_column('apitokens', 'resourcescopes')
|