- Anmeldung über Argon2id und JWT in httpOnly-Cookies, Refresh mit echter Rotation über die neue Tabelle refresh_token - AuthProvider-Protokoll als Vorbereitung für OIDC, Administrator-Anlage beim Erststart mit erzwungenem Passwortwechsel - CRUD für Konten, Kategorien (zweistufiger Baum), Firmen, Recurrences, Preisversionen, Buchungen, Budgets, Vorlagen und Sparziele - Fälligkeiten mit Overlay-Logik: abrufen, bestätigen, auslassen, zurücksetzen - Kontosalden zum Stichtag, Monatsübersicht mit Plan-Ist-Vergleich - SECRET_KEY jetzt mindestens 32 Zeichen; Platzhalter in Produktion abgelehnt - 61 neue Integrationstests, insgesamt 148 grün Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014e7t8UpmoVNMtWivY5LiSH
41 lines
1.5 KiB
Python
41 lines
1.5 KiB
Python
"""refresh token rotation
|
|
|
|
Revision ID: 07d8d62011b3
|
|
Revises: 2bc4ab55dbe9
|
|
Create Date: 2026-09-09 13:23:58.343172+02:00
|
|
"""
|
|
|
|
from collections.abc import Sequence
|
|
|
|
import sqlalchemy as sa
|
|
from alembic import op
|
|
|
|
revision: str = '07d8d62011b3'
|
|
down_revision: str | None = '2bc4ab55dbe9'
|
|
branch_labels: str | Sequence[str] | None = None
|
|
depends_on: str | Sequence[str] | None = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.create_table('refresh_token',
|
|
sa.Column('id', sa.Integer(), nullable=False),
|
|
sa.Column('jti', sa.String(length=64), nullable=False),
|
|
sa.Column('user_id', sa.Integer(), nullable=False),
|
|
sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
|
|
sa.Column('created_at', sa.DateTime(timezone=True), nullable=False),
|
|
sa.ForeignKeyConstraint(['user_id'], ['app_user.id'], name=op.f('fk_refresh_token_user_id_app_user'), ondelete='CASCADE'),
|
|
sa.PrimaryKeyConstraint('id', name=op.f('pk_refresh_token')),
|
|
sa.UniqueConstraint('jti', name=op.f('uq_refresh_token_jti'))
|
|
)
|
|
op.create_index('ix_refresh_token_user_id', 'refresh_token', ['user_id'], unique=False)
|
|
# ### end Alembic commands ###
|
|
|
|
|
|
def downgrade() -> None:
|
|
# ### commands auto generated by Alembic - please adjust! ###
|
|
op.drop_index('ix_refresh_token_user_id', table_name='refresh_token')
|
|
op.drop_table('refresh_token')
|
|
# ### end Alembic commands ###
|