Files
shaguabijia-app-server/alembic/versions/push_binding_isolation.py
T
2026-07-31 14:34:07 +08:00

90 lines
2.6 KiB
Python

"""isolate vendor push binding across user accounts
Revision ID: push_binding_isolation
Revises: guide_video_ten_circle_v2
"""
from __future__ import annotations
import sqlalchemy as sa
from alembic import op
revision = "push_binding_isolation"
down_revision = "guide_video_ten_circle_v2"
branch_labels = None
depends_on = None
def upgrade() -> None:
with op.batch_alter_table("device_liveness") as batch_op:
batch_op.add_column(sa.Column("push_binding_id", sa.String(length=128), nullable=True))
batch_op.add_column(
sa.Column(
"push_binding_revoked",
sa.Boolean(),
nullable=False,
server_default=sa.false(),
)
)
batch_op.create_index(
"ix_device_liveness_push_binding_id",
["push_binding_id"],
unique=False,
)
connection = op.get_bind()
device = sa.table(
"device_liveness",
sa.column("id", sa.Integer),
sa.column("push_vendor", sa.String),
sa.column("push_token", sa.String),
sa.column("updated_at", sa.DateTime),
)
connection.execute(
device.update()
.where(
sa.or_(
device.c.push_vendor == "",
device.c.push_token == "",
)
)
.values(push_vendor=None, push_token=None)
)
rows = connection.execute(
sa.select(device.c.id, device.c.push_vendor, device.c.push_token)
.where(
device.c.push_vendor.is_not(None),
device.c.push_token.is_not(None),
)
.order_by(device.c.updated_at.desc(), device.c.id.desc())
)
seen: set[tuple[str, str]] = set()
duplicate_ids: list[int] = []
for row in rows:
key = (row.push_vendor, row.push_token)
if key in seen:
duplicate_ids.append(row.id)
else:
seen.add(key)
if duplicate_ids:
connection.execute(
device.update()
.where(device.c.id.in_(duplicate_ids))
.values(push_vendor=None, push_token=None)
)
with op.batch_alter_table("device_liveness") as batch_op:
batch_op.create_unique_constraint(
"uq_device_liveness_vendor_token",
["push_vendor", "push_token"],
)
def downgrade() -> None:
with op.batch_alter_table("device_liveness") as batch_op:
batch_op.drop_constraint("uq_device_liveness_vendor_token", type_="unique")
batch_op.drop_index("ix_device_liveness_push_binding_id")
batch_op.drop_column("push_binding_revoked")
batch_op.drop_column("push_binding_id")