Skip to content

Commit

Permalink
Updating users endpoint comments
Browse files Browse the repository at this point in the history
  • Loading branch information
giosava94 committed Apr 23, 2024
1 parent c170835 commit 153e1ce
Show file tree
Hide file tree
Showing 3 changed files with 58 additions and 20 deletions.
2 changes: 2 additions & 0 deletions fed_mng/api/dependencies.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Dependencies of the users endpoints."""
from fastapi import Depends, HTTPException, status
from sqlmodel import Session, select

Expand All @@ -6,6 +7,7 @@


def check_user_exists(user_id: int, session: Session = Depends(get_session)) -> User:
"""If the user does not exist, raise a 404 error, otherwise return the user."""
user = session.exec(select(User).filter(User.id == user_id)).first()
if not user:
raise HTTPException(
Expand Down
27 changes: 27 additions & 0 deletions fed_mng/api/utils.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Utilities for the users endpoints."""
from typing import Sequence, Type

from sqlmodel import Session, select
Expand Down Expand Up @@ -27,6 +28,15 @@ def change_role(
| Type[UserGroupManager],
enable_role: bool | None,
) -> User:
"""Change user role.
If `enable_role` is None, do nothing. Otherwise if `enable_role` is true and the
user does not alreay have this role, give it. On the other hand if `enable_role`
is false and the user already has that role, revoke it.
Return the user updated instance.
"""

if enable_role is not None:
user_role = session.exec(select(role).filter(role.id == user.id)).first()
if enable_role and user_role is None:
Expand All @@ -48,13 +58,23 @@ def filter_role(
| Type[UserGroupManager],
match_role: bool | None,
) -> SelectOfScalar[User]:
"""Filter user by role.
If `match_role` is None, do nothing. Otherwise if `match_role` is true, add to the
statement a join condition to match users having that role. On the other hand if
`match_role` is false, update the statement to exclude users having that role.
Return the updated statement.
"""

if match_role is True:
return statement.join(role)
elif match_role is False:
return statement.join(role, isouter=True).filter(role.id == None) # noqa: E711


def create_user(session: Session, user: UserCreate) -> User:
"""Create a user."""
item = User(**user.model_dump())
session.add(item)
session.commit()
Expand All @@ -64,6 +84,13 @@ def create_user(session: Session, user: UserCreate) -> User:
def retrieve_users(
session: Session, user: UserQuery, query: Query, role: RoleQuery
) -> Sequence[User]:
"""Get list of users.
If specified, filter by user attributes and roles. Paginate resulting list.
Sort the list by the given attribute (both ascending or descending order).
Return the list of filtered and sorted items.
"""
statement = select(User)
for k, v in user.model_dump(exclude_none=True).items():
statement = statement.filter(getattr(User, k) == v)
Expand Down
49 changes: 29 additions & 20 deletions fed_mng/api/v1/users.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Users endpoints."""
from fastapi import APIRouter, Depends, HTTPException, Request, Security, status
from fastapi.security import HTTPBasicCredentials
from sqlalchemy.exc import IntegrityError
Expand Down Expand Up @@ -27,9 +28,12 @@
@router.get(
"/",
summary="Read all users",
description="Retrieve all loaded process specifications. Each returned tuple \
contains the specification's ID, the process name and the path to the original \
BPMN file.",
description="""
Retrieve all registered users with their attributes.
If specified, results can be filtered by attribute and role. It is possible to
paginate results (by default the endpoint returns at most 100 items). Results can
be sorted, both ascending and descending order, by any of the user attribute.
""",
)
@flaat.access_level("admin")
def get_user_list(
Expand All @@ -47,26 +51,28 @@ def get_user_list(
@router.get(
"/{user_id}",
summary="Read specific user",
description="Retrieve all loaded process specifications. Each returned tuple \
contains the specification's ID, the process name and the path to the original \
BPMN file.",
description="""
Retrieve the user matching the received `user_id`. If the target item does not
exist, raise a `404 not found` error.
""",
)
@flaat.access_level("admin")
def get_user(
request: Request,
user: User = Depends(check_user_exists),
client_credentials: HTTPBasicCredentials = Security(security),
) -> User:
"""GET operation to retrieve all users."""
"""GET operation to retrieve a specific user."""
return user


@router.delete(
"/{user_id}",
summary="Delete specific user",
description="Retrieve all loaded process specifications. Each returned tuple \
contains the specification's ID, the process name and the path to the original \
BPMN file.",
description="""
Delete the user matching the received `user_id`. Automatically remove the associated
roles. If the target item does not exist, raise a `404 not found` error.
""",
status_code=status.HTTP_204_NO_CONTENT,
)
@flaat.access_level("admin")
Expand All @@ -76,17 +82,18 @@ def delete_user(
session: Session = Depends(get_session),
client_credentials: HTTPBasicCredentials = Security(security),
) -> None:
"""GET operation to retrieve all users."""
"""DELETE operation to remove a specific user."""
session.delete(user)
session.commit()


@router.post(
"/",
summary="Create new user",
description="Retrieve all loaded process specifications. Each returned tuple \
contains the specification's ID, the process name and the path to the original \
BPMN file.",
description="""Create a new user with the given attributes. During creation, it is
possible to assign roles to the user. If an item with the same `email` already
exists, raise a `422 validation` error.
""",
status_code=status.HTTP_201_CREATED,
)
@flaat.access_level("admin")
Expand All @@ -97,7 +104,7 @@ def post_user(
role: RoleQuery = Depends(),
client_credentials: HTTPBasicCredentials = Security(security),
) -> User:
"""GET operation to retrieve all users."""
"""POST operation to create a user and, optionally, assign multiple roles."""
try:
item = create_user(session, user)
except IntegrityError as exc:
Expand All @@ -115,10 +122,12 @@ def post_user(

@router.put(
"/{user_id}",
summary="Update user",
description="Retrieve all loaded process specifications. Each returned tuple \
contains the specification's ID, the process name and the path to the original \
BPMN file.",
summary="Update a specific user",
description="""
Update the attributes of a specific user. It is possible to assign or revoke roles
to the target user. If the target item does not exist, raise a `404 not found`
error.
""",
)
@flaat.access_level("admin")
def put_user(
Expand All @@ -129,7 +138,7 @@ def put_user(
role: RoleQuery = Depends(),
client_credentials: HTTPBasicCredentials = Security(security),
) -> User:
"""GET operation to retrieve all users."""
"""PUT operation to update a specific user."""
for k, v in new_data.model_dump(exclude_none=True).items():
user.__setattr__(k, v)
user = change_role(session, user, Admin, role.is_admin)
Expand Down

0 comments on commit 153e1ce

Please sign in to comment.