From 3b8d4062a037affa096b7a6788b1629199b6ff99 Mon Sep 17 00:00:00 2001 From: CarlosOchoa8 Date: Fri, 18 Jul 2025 15:35:21 -0600 Subject: [PATCH 1/2] feat(user): is_locked & locked_until fields added into model and its corresponding migration --- ..._1759_3b7b1c985503_add_user_lock_fields.py | 37 +++++++++++++++++++ backend/app/models/user.py | 12 ++++++ 2 files changed, 49 insertions(+) create mode 100644 backend/alembic/versions/20250706_1759_3b7b1c985503_add_user_lock_fields.py 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..a17f9f9 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -166,6 +166,18 @@ 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" From ab9c032e713c397c35f43e3fd92255cc6fcd4af8 Mon Sep 17 00:00:00 2001 From: CarlosOchoa8 Date: Fri, 18 Jul 2025 15:55:51 -0600 Subject: [PATCH 2/2] fix: resolve linting issues --- backend/app/models/user.py | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/backend/app/models/user.py b/backend/app/models/user.py index a17f9f9..c397086 100644 --- a/backend/app/models/user.py +++ b/backend/app/models/user.py @@ -167,15 +167,11 @@ class User(Base): ) is_locked: Mapped[bool] = mapped_column( - Boolean, - default=False, - nullable=False, - comment="User login is locked." + 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." + DateTime(timezone=True), comment="User login allowed in time." ) # OAuth and external accounts