diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 03f0a88..2ad05ca 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -17,20 +17,6 @@ jobs: POETRY_VIRTUALENVS_CREATE: false - name: Run black check run: poetry run black --check . - mypy: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v2 - - name: Set up Python - uses: actions/setup-python@v2 - with: - python-version: '3.9' - - name: Install deps - uses: knowsuchagency/poetry-install@v1 - env: - POETRY_VIRTUALENVS_CREATE: false - - name: Run mypy check - run: poetry run mypy . pytest: runs-on: ubuntu-latest services: diff --git a/README.md b/README.md index 081f927..49b1966 100644 --- a/README.md +++ b/README.md @@ -85,7 +85,6 @@ It's configured using .pre-commit-config.yaml file. By default it runs: * black (formats your code); -* mypy (validates types); * isort (sorts imports in all files); diff --git a/gestao/db/migrations/versions/2023-10-28-21-20_05258d089f10.py b/gestao/db/migrations/versions/2023-10-28-21-20_05258d089f10.py index 0614837..3d6912c 100644 --- a/gestao/db/migrations/versions/2023-10-28-21-20_05258d089f10.py +++ b/gestao/db/migrations/versions/2023-10-28-21-20_05258d089f10.py @@ -23,9 +23,13 @@ def upgrade(): batch_op.add_column( sa.Column("nickname", sa.String(200), nullable=True), ) + batch_op.add_column( + sa.Column("status", sa.String(200), default="active"), + ) def downgrade(): with op.batch_alter_table("user") as batch_op: batch_op.drop_column("workstation") batch_op.drop_column("nickname") + batch_op.drop_column("status") diff --git a/gestao/db/models/user.py b/gestao/db/models/user.py index 9a8cf10..65559e5 100644 --- a/gestao/db/models/user.py +++ b/gestao/db/models/user.py @@ -37,6 +37,7 @@ class Meta(BaseMeta): role: str = ormar.String(max_length=200) category: str = ormar.String(max_length=200) pattern: str = ormar.String(max_length=200) + status: str = ormar.String(max_length=200, default="active") workstation: Optional[str] = ormar.String(max_length=200, nullable=True) nickname: Optional[str] = ormar.String(max_length=200, unique=True, nullable=True) dispatcher: str = ormar.String(max_length=200) diff --git a/gestao/web/api/user/enums.py b/gestao/web/api/user/enums.py new file mode 100644 index 0000000..430ded0 --- /dev/null +++ b/gestao/web/api/user/enums.py @@ -0,0 +1,6 @@ +from enum import Enum + + +class UserStatus(str, Enum): + active = "active" + inactive = "inactive" diff --git a/gestao/web/api/user/schema.py b/gestao/web/api/user/schemas.py similarity index 98% rename from gestao/web/api/user/schema.py rename to gestao/web/api/user/schemas.py index fbed273..00f1acb 100644 --- a/gestao/web/api/user/schema.py +++ b/gestao/web/api/user/schemas.py @@ -79,3 +79,4 @@ class UpdateUserDTO(BaseModel): dispatched_date: Optional[date] workstation: Optional[str] nickname: Optional[str] + status: Optional[str] diff --git a/gestao/web/api/user/views.py b/gestao/web/api/user/views.py index 98ed083..a130a89 100644 --- a/gestao/web/api/user/views.py +++ b/gestao/web/api/user/views.py @@ -2,11 +2,13 @@ from typing import List from uuid import uuid4 +from asyncpg.exceptions import UniqueViolationError from fastapi import APIRouter, HTTPException from gestao.db.models.dependent import Dependent from gestao.db.models.user import User -from gestao.web.api.user.schema import CreateUserDTO, UpdateUserDTO +from gestao.web.api.user.enums import UserStatus +from gestao.web.api.user.schemas import CreateUserDTO, UpdateUserDTO router = APIRouter() @@ -16,13 +18,22 @@ async def get_users( limit: int = 10, offset: int = 0, ) -> List[User]: - return await User.objects.limit(limit).offset(offset).all() + return ( + await User.objects.limit(limit) + .offset( + offset, + ) + .filter(status=UserStatus.active) + .all() + ) @router.get("/{user_id}", response_model_exclude={"dependents__user_id"}) async def get_user(user_id: str) -> User: try: - return await User.objects.select_related(User.dependents).get(id=user_id) + return await User.objects.select_related( + User.dependents, + ).get(id=user_id) except Exception: logging.error("Error occurred while get user", exc_info=True) raise HTTPException(status_code=404, detail="User not found") @@ -34,7 +45,9 @@ async def create_user(create_user: CreateUserDTO) -> User: create_user_dict = create_user.dict() dependents = create_user_dict.pop("dependents", []) user_id = str(uuid4()) - await User.objects.create(id=user_id, **create_user_dict) + await User.objects.create( + id=user_id, **create_user_dict, status=UserStatus.active + ) if dependents: await Dependent.objects.bulk_create( [ @@ -43,6 +56,12 @@ async def create_user(create_user: CreateUserDTO) -> User: ], ) return await User.objects.select_related(User.dependents).get(id=user_id) + except UniqueViolationError: + logging.error("User already exists", exc_info=True) + raise HTTPException( + status_code=400, + detail="User already exists", + ) except Exception: logging.error("Error occurred while creating user", exc_info=True) raise HTTPException( @@ -54,16 +73,14 @@ async def create_user(create_user: CreateUserDTO) -> User: @router.put("/{user_id}", response_model_exclude={"dependents__user_id"}) async def update_user(user_id: str, update_user: UpdateUserDTO) -> User: try: - await User.objects.filter(id=user_id).update( - each=True, - **update_user.dict(exclude_none=True), - ) + user = await User.objects.get(id=user_id) + await user.update(**update_user.dict(exclude_none=True)) return await User.objects.select_related(User.dependents).get(id=user_id) except Exception: - logging.error("Error occurred while updating user", exc_info=True) + logging.error("User not found", exc_info=True) raise HTTPException( status_code=404, - detail="Error occurred while updating user", + detail="User not found", ) @@ -77,3 +94,17 @@ async def delete_user(user_id: str) -> None: status_code=404, detail="Error occurred while deleting user", ) + + +@router.patch("/{user_id}/disable") +async def disable_user(user_id: str) -> None: + try: + user = await User.objects.get(id=user_id) + await user.update(status=UserStatus.inactive) + return {"detail": "User disabled successfully"} + except Exception: + logging.error("User not found", exc_info=True) + raise HTTPException( + status_code=404, + detail="User not found", + ) diff --git a/pyproject.toml b/pyproject.toml index f33c1a0..e9e6ed8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -44,19 +44,6 @@ profile = "black" multi_line_output = 3 src_paths = ["gestao",] -[tool.mypy] -strict = true -ignore_missing_imports = true -allow_subclassing_any = true -allow_untyped_calls = true -pretty = true -show_error_codes = true -implicit_reexport = true -allow_untyped_decorators = true -warn_unused_ignores = false -warn_return_any = false -namespace_packages = true - [tool.pytest.ini_options] filterwarnings = [ "error",