diff --git a/backend/alembic/versions/20250706_1759_3b7b1c985503_add_user_lock_fields.py b/backend/alembic/versions/20250706_1759_3b7b1c985503_add_user_lock_fields.py new file mode 100644 index 0000000..c0383e7 --- /dev/null +++ b/backend/alembic/versions/20250706_1759_3b7b1c985503_add_user_lock_fields.py @@ -0,0 +1,37 @@ +"""add user lock fields + +Revision ID: 3b7b1c985503 +Revises: d257b753aa69 +Create Date: 2025-07-06 17:59:37.747302+00:00 + +🚧 SMITHY MIGRATION 🚧 +This file was automatically forged by Alembic. +Edit only if you know what you're doing. +""" +from typing import Sequence, Union + +from alembic import op # type: ignore +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '3b7b1c985503' +down_revision: Union[str, Sequence[str], None] = 'd257b753aa69' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.add_column('users', sa.Column('is_locked', sa.Boolean(), nullable=False, comment='User login is locked.')) + op.add_column('users', sa.Column('locked_until', sa.DateTime(timezone=True), nullable=True, comment='User login allowed in time.')) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('users', 'locked_until') + op.drop_column('users', 'is_locked') + # ### end Alembic commands ### diff --git a/backend/app/models/user.py b/backend/app/models/user.py index 748ca75..c397086 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -166,6 +166,14 @@ class User(Base): Integer, default=0, nullable=False, comment="Consecutive failed login attempts" ) + is_locked: Mapped[bool] = mapped_column( + Boolean, default=False, nullable=False, comment="User login is locked." + ) + + locked_until: Mapped[Optional[datetime]] = mapped_column( + DateTime(timezone=True), comment="User login allowed in time." + ) + # OAuth and external accounts oauth_accounts: Mapped[Optional[dict]] = mapped_column( JSONB, nullable=True, comment="Connected OAuth accounts data"