Jul 10 - Update facility's area with QR code

This commit is contained in:
2026-07-10 14:05:54 -04:00
parent 008dd94962
commit 512a80837a
8 changed files with 635 additions and 6 deletions
@@ -0,0 +1,71 @@
"""phase39 — areas.public_token for per-area public QR landing pages
Adds a unique, unguessable token per area. Each area's QR code encodes
/f/area/<public_token>, an occupant-friendly summary scoped to that area plus
a "report a problem" form (login-free). Existing areas are backfilled with a
generated token.
Uses INFORMATION_SCHEMA checks — safe to re-run.
"""
revision = 'phase39_area_public_token'
down_revision = 'phase38_support_knowledge'
branch_labels = None
depends_on = None
import secrets
from alembic import op
import sqlalchemy as sa
def _column_exists(conn, table, column):
result = conn.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS "
"WHERE TABLE_SCHEMA = DATABASE() "
"AND TABLE_NAME = :t AND COLUMN_NAME = :c"
), {"t": table, "c": column})
return result.scalar() > 0
def upgrade():
bind = op.get_bind()
if not _column_exists(bind, 'areas', 'public_token'):
op.execute(sa.text(
"ALTER TABLE areas ADD COLUMN public_token VARCHAR(48) NULL"
))
# Backfill a unique token for every existing area that lacks one.
rows = bind.execute(sa.text(
"SELECT id FROM areas WHERE public_token IS NULL OR public_token = ''"
)).fetchall()
for (aid,) in rows:
token = secrets.token_urlsafe(24)
bind.execute(
sa.text("UPDATE areas SET public_token = :tok WHERE id = :id"),
{"tok": token, "id": aid},
)
# Enforce uniqueness now that every row has a value.
existing_idx = bind.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'areas' "
"AND INDEX_NAME = 'uq_area_public_token'"
)).scalar()
if not existing_idx:
op.execute(sa.text(
"CREATE UNIQUE INDEX uq_area_public_token ON areas (public_token)"
))
def downgrade():
bind = op.get_bind()
existing_idx = bind.execute(sa.text(
"SELECT COUNT(*) FROM INFORMATION_SCHEMA.STATISTICS "
"WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'areas' "
"AND INDEX_NAME = 'uq_area_public_token'"
)).scalar()
if existing_idx:
op.execute(sa.text("DROP INDEX uq_area_public_token ON areas"))
if _column_exists(bind, 'areas', 'public_token'):
op.execute(sa.text("ALTER TABLE areas DROP COLUMN public_token"))