Files
ForbiddenStarsApp/backend/alembic/versions/0013_user_token_version.py
T
NotBigGhostandClaude Opus 4.8 3f8667b561 Отзыв JWT при выходе и смене пароля
logout отзывает предъявленный токен по jti (in-memory denylist до exp);
смена и сброс пароля инкрементят users.token_version (claim ver в JWT,
сверка в auth/deps) — все прежние сессии отзываются. Своё устройство при
смене пароля остаётся в сессии (перевыдача cookie). Миграция 0013. #57

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XfTsytzT6TojfmprRDKiV6
2026-09-13 17:09:57 +03:00

45 lines
1.6 KiB
Python

"""Пользователь: версия сессий (token_version) для отзыва JWT.
Идемпотентна: на свежей БД столбец создаёт 0001 (create_all из актуальных моделей) -> no-op;
на существующей БД добавляет столбец. render_as_batch включён в env.py (для SQLite).
Инкремент token_version отзывает все ранее выданные токены пользователя (см. auth/deps, #57).
Revision ID: 0013_user_token_version
Revises: 0012_match_finish_draft
Create Date: 2026-09-13
"""
from typing import Sequence, Union
import sqlalchemy as sa
from sqlalchemy import inspect
from alembic import op
revision: str = "0013_user_token_version"
down_revision: Union[str, None] = "0012_match_finish_draft"
branch_labels: Union[str, Sequence[str], None] = None
depends_on: Union[str, Sequence[str], None] = None
def upgrade() -> None:
bind = op.get_bind()
insp = inspect(bind)
cols = {c["name"] for c in insp.get_columns("users")}
with op.batch_alter_table("users") as b:
if "token_version" not in cols:
b.add_column(
sa.Column(
"token_version", sa.Integer(), nullable=False, server_default="0"
)
)
def downgrade() -> None:
bind = op.get_bind()
insp = inspect(bind)
cols = {c["name"] for c in insp.get_columns("users")}
with op.batch_alter_table("users") as b:
if "token_version" in cols:
b.drop_column("token_version")