Skip to content

Commit

Permalink
Merge HAN-138: Agregar endpoint para obtener usuarios con filtro por …
Browse files Browse the repository at this point in the history
…nickname (#25)
  • Loading branch information
violetaperezandrade authored May 29, 2024
1 parent ef9c108 commit 4134552
Show file tree
Hide file tree
Showing 8 changed files with 138 additions and 39 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: Tests
on:
push:
branches:
- main
- master
- develop
pull_request:
branches:
Expand Down
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,6 @@ docker-compose-down:
docker-compose-logs:
docker-compose -f docker-compose.yaml logs -f
.PHONY: docker-compose-logs

magic: docker-compose-down docker-compose-up docker-compose-logs
.PHONY: magic
26 changes: 7 additions & 19 deletions app/controller/Users.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from fastapi import status
from fastapi import status, Response
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from external.Social import SocialService
Expand All @@ -19,27 +19,15 @@ def handle_get_user(self, user_id: int):
})
)

def handle_get_all_users(self, ids: list | None = None):
if ids:
ids = ids[0].split(",")
ids = [x for x in ids if x.isdigit()]
users = self.users_service.get_users_by_ids(ids)
def handle_get_users(self, query_params: dict):
users = self.users_service.get_users(query_params)
if users:
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": users,
"status": status.HTTP_200_OK,
})
)
else:
users = self.users_service.get_all_users()
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": users,
"status": status.HTTP_200_OK,
}),
)
"message": users})
)
return Response(status_code=status.HTTP_204_NO_CONTENT)

async def handle_create_user(self, user_data: dict):
result = self.users_service.create_user(user_data)
Expand Down
15 changes: 10 additions & 5 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
from fastapi import Depends, FastAPI, Query
from fastapi import Depends, FastAPI
from controller.Users import UsersController
from service.Users import UsersService
from repository.Users import UsersRepository
from typing import List, Annotated, Union
from typing import Annotated
from schemas.Schemas import (
CreateUserSchema,
UpdateUserSchema,
LoginRequest,
CreateNotificationSchema,
UpdateNotificationSchema
)
from query_params.QueryParams import GetUsersQueryParams
from security.JWTBearer import get_current_user_id


Expand All @@ -30,13 +31,17 @@ def root():


@app.get("/users/{user_id}", tags=["Users"])
def get_users(user_id: int):
def get_user(user_id: int):
return users_controller.handle_get_user(user_id)


@app.get("/users", tags=["Users"])
def get_all_users(ids: Annotated[Union[List[str], None], Query()] = None):
return users_controller.handle_get_all_users(ids)
def get_users(
query_params: GetUsersQueryParams = Depends(GetUsersQueryParams)
):
return users_controller.handle_get_users(
query_params.get_query_params()
)


@app.post("/users", tags=["Users"])
Expand Down
29 changes: 29 additions & 0 deletions app/query_params/QueryParams.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from fastapi import Query
from typing import Optional


def get_query_params(query_params_dic: dict):
filters = {}
for filterName, value in query_params_dic.items():
if value is not None:
filters[filterName] = value.lower() if value is str else value
return filters


class GetUsersQueryParams:
def __init__(
self,
offset: Optional[int] = Query(0, ge=0),
limit: Optional[int] = Query(200, le=200),
ids: Optional[str] = Query(None),
nickname: Optional[str] = Query(None),
):
self.query_params = {
'offset': offset,
'limit': limit,
'ids': ids,
'nickname': nickname
}

def get_query_params(self):
return get_query_params(self.query_params)
14 changes: 10 additions & 4 deletions app/repository/Users.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,18 @@ def get_user_by_email(self, email: str):
user = self.session.query(User).filter_by(email=email).first()
return user.__dict__ if user else None

def get_all_users(self, ids: list = None):
users = self.session.query(User).all()
def get_all_users(self, limit: int, offset: int):
users = self.session.query(User).offset(offset).limit(limit).all()
return self.__parse_result(users)

def get_users_by_ids(self, ids: list):
users = self.session.query(User).filter(User.id.in_(ids)).all()
def get_users_by_ids(self, ids: list, limit: int, offset: int):
users = self.session.query(User).filter(User.id.in_(ids)).offset(
offset).limit(limit).all()
return self.__parse_result(users)

def get_user_by_nickname(self, nickname: str, limit: int, offset: int):
users = self.session.query(User).filter(User.nickname.ilike(
f"{nickname}%")).offset(offset).limit(limit).all()
return self.__parse_result(users)

@withSQLExceptionsHandle()
Expand Down
17 changes: 14 additions & 3 deletions app/service/Users.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,20 @@ def get_user(self, user_id: int):
raise ResourceNotFound(user_id, "User")
return user

def get_all_users(self):
return self.user_repository.get_all_users()
def get_users(self, query_params: dict):
ids = query_params.get("ids", None)
nickname = query_params.get("nickname", None)
offset = query_params.get("offset", 0)
limit = query_params.get("limit", 200)

if ids:
ids = ids.split(",")
ids = [x for x in ids if x.isdigit()]
return self.user_repository.get_users_by_ids(ids, limit, offset)
if nickname:
return self.user_repository.get_user_by_nickname(nickname, limit,
offset)
return self.user_repository.get_all_users(limit, offset)

def get_users_by_ids(self, ids: list):
return self.user_repository.get_users_by_ids(ids)
Expand Down Expand Up @@ -112,7 +124,6 @@ def login(self, auth_code: str):
user = self.user_repository.get_user_by_email(user_info["email"])

if user is None:
print(f"user info: {user_info}")
if "name" in user_info:
name = user_info["name"]
else:
Expand Down
71 changes: 64 additions & 7 deletions app/tests/test_users.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,24 +90,81 @@ def test_raise_user_not_found(self):
with self.assertRaises(ResourceNotFound):
service.get_user(10)

def test_get_all_users(self):
def test_get_users_without_params(self):
attr_db = {"get_all_users.return_value": [john, alice]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
users = service.get_all_users()
query_params = {}
users = service.get_users(query_params)

self.assertEqual(len(users), 2)
mock_db.get_all_users.assert_called_once()

def test_get_users_by_id(self):
def test_get_users_with_limit_and_offset(self):
attr_db = {"get_all_users.return_value": [john]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
query_params = {"limit": 1, "offset": 0}
users = service.get_users(query_params)

self.assertEqual(len(users), 1)
self.assertEqual(users[0], john)
mock_db.get_all_users.assert_called_once_with(1, 0)

def test_get_users_by_ids(self):
attr_db = {"get_users_by_ids.return_value": [john, alice]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
users = service.get_users_by_ids([1, 2])
query_params = {"ids": "1,2"}
users = service.get_users(query_params)

self.assertEqual(len(users), 2)
self.assertTrue(john in users)
self.assertTrue(alice in users)
mock_db.get_users_by_ids.assert_called_once_with(['1', '2'], 200, 0)

def test_get_users_by_nickname(self):
attr_db = {"get_user_by_nickname.return_value": [john]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
query_params = {"nickname": "john"}
users = service.get_users(query_params)

self.assertEqual(len(users), 1)
self.assertTrue(john in users)
mock_db.get_user_by_nickname.assert_called_once_with("john", 200, 0)

def test_get_users_by_ids_invalid_ids(self):
attr_db = {"get_users_by_ids.return_value": []}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
query_params = {"ids": "abc,2,,"}
users = service.get_users(query_params)

self.assertEqual(len(users), 0)
mock_db.get_users_by_ids.assert_called_once_with(['2'], 200, 0)

def test_get_users_by_nickname_with_limit_and_offset(self):
attr_db = {"get_user_by_nickname.return_value": [john]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
query_params = {"nickname": "john", "limit": 1, "offset": 0}
users = service.get_users(query_params)

self.assertEqual(len(users), 1)
self.assertTrue(john in users)
mock_db.get_user_by_nickname.assert_called_once_with("john", 1, 0)

def test_get_users_by_ids_with_limit_and_offset(self):
attr_db = {"get_users_by_ids.return_value": [john]}
mock_db = get_mock(UsersRepository, attr_db)
service = UsersService(mock_db)
query_params = {"ids": "1", "limit": 1, "offset": 0}
users = service.get_users(query_params)

self.assertTrue(users.__contains__(john))
self.assertTrue(users.__contains__(alice))
mock_db.get_users_by_ids.assert_called_once_with([1, 2])
self.assertEqual(len(users), 1)
self.assertTrue(john in users)
mock_db.get_users_by_ids.assert_called_once_with(['1'], 1, 0)

def test_create_user(self):
attr_db = {
Expand Down

0 comments on commit 4134552

Please sign in to comment.