diff --git a/app/db/crud.py b/app/db/crud.py index 97c8edf..0123b67 100644 --- a/app/db/crud.py +++ b/app/db/crud.py @@ -232,7 +232,7 @@ def get_users( data_limit_reached: bool | None = None, enabled: bool | None = None, ) -> Union[List[User], Tuple[List[User], int]]: - query = db.query(User) + query = db.query(User).filter(User.removed == False) if usernames: if len(usernames) == 1: @@ -382,7 +382,8 @@ def create_user( def remove_user(db: Session, dbuser: User): - db.delete(dbuser) + dbuser.removed = True + dbuser.activated = False # db.query(User).filter_by(id=user_id).delete() db.commit() diff --git a/app/db/migrations/versions/b0357faf51c8_add_removed_to_users.py b/app/db/migrations/versions/b0357faf51c8_add_removed_to_users.py new file mode 100644 index 0000000..dff687b --- /dev/null +++ b/app/db/migrations/versions/b0357faf51c8_add_removed_to_users.py @@ -0,0 +1,37 @@ +"""add removed to users for soft delete + +Revision ID: b0357faf51c8 +Revises: 3acfdeb79b78 +Create Date: 2024-07-14 19:58:54.430547 + +""" + +import sqlalchemy as sa +from alembic import op + +# revision identifiers, used by Alembic. +revision = "b0357faf51c8" +down_revision = "3acfdeb79b78" +branch_labels = None +depends_on = None + + +def upgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.add_column( + "users", + sa.Column( + "removed", + sa.Boolean(), + server_default=sa.sql.false(), + nullable=False, + ), + ) + + # ### end Alembic commands ### + + +def downgrade() -> None: + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column("users", "removed") + # ### end Alembic commands ### diff --git a/app/db/models.py b/app/db/models.py index 7c03595..b966739 100644 --- a/app/db/models.py +++ b/app/db/models.py @@ -153,6 +153,12 @@ class User(Base): default=True, server_default=sqlalchemy.sql.true(), ) + removed = Column( + Boolean, + nullable=False, + default=False, + server_default=sqlalchemy.sql.false(), + ) services = relationship( "Service", secondary=users_services, @@ -237,12 +243,20 @@ class User(Base): @hybrid_property def is_active(self): return ( - self.enabled and not self.expired and not self.data_limit_reached + self.enabled + and not self.expired + and not self.data_limit_reached + and not self.removed ) @is_active.expression def is_active(cls): - return and_(cls.enabled == True, ~cls.expired, ~cls.data_limit_reached) + return and_( + cls.enabled == True, + ~cls.expired, + ~cls.data_limit_reached, + ~cls.removed, + ) @property def status(self): diff --git a/app/routes/user.py b/app/routes/user.py index 4ce6bb7..707e13c 100644 --- a/app/routes/user.py +++ b/app/routes/user.py @@ -70,7 +70,7 @@ def get_users( """ dbadmin = crud.get_admin(db, admin.username) - query = db.query(User) + query = db.query(User).filter(User.removed == False) admin = dbadmin if not admin.is_sudo else None @@ -171,14 +171,13 @@ async def delete_expired( expired_users = [ user for user in db_users - if user.expire is not None and user.expire <= expiration_threshold + if user.expire_date is not None + and user.expire_date <= expiration_threshold ] if not expired_users: raise HTTPException(status_code=404, detail="No expired user found.") for db_user in expired_users: - if db_user.activated and not db_user.is_active: - marznode.operations.update_user(db_user) crud.remove_user(db, db_user) asyncio.ensure_future(