Skip to content

Commit 3e213cf

Browse files
Merge pull request #6 from Cinnamoon-dev/refactor/services
refactor: services
2 parents 115fe9c + 5039233 commit 3e213cf

8 files changed

Lines changed: 65 additions & 55 deletions

File tree

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
clean:
2-
rm -rf $(shell find . | grep cache)
2+
rm -rf $(shell find . | grep __pycache__)
33

44
populate:
55
uv run python3 -m src.infra.database.populate

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ dependencies = [
1010
"passlib[bcrypt]>=1.7.4",
1111
"psycopg2-binary>=2.9.10",
1212
"pydantic[email]>=2.11.7",
13-
"pyjwt==2.10.0",
13+
"pyjwt>=2.10.1",
1414
"pytest>=8.4.1",
1515
"python-multipart>=0.0.20",
1616
"uvicorn>=0.35.0",

src/controllers/userController.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from fastapi.responses import JSONResponse
12
from fastapi import APIRouter, Depends, Request
23

34
from ._helpers import PermissionChecker
@@ -23,26 +24,34 @@ def user_view(
2324
user_id: int,
2425
perms = Depends(PermissionChecker("usuario-view"))
2526
):
26-
return UserService().view(user_id)
27+
user = UserService().view(user_id)
28+
29+
if user is None:
30+
return JSONResponse(status_code=404, content={"error": True, "message": f"User with id {user_id} not found"})
31+
32+
return JSONResponse(status_code=200, content={"error": False, "data": user})
2733

2834
@router.post("/")
2935
def user_add(
3036
user: UserAddSchema,
3137
perms = Depends(PermissionChecker("usuario-add"))
3238
):
33-
return UserService().add(user)
39+
inserted_id = UserService().add(user)
40+
return JSONResponse(status_code=200, content={"error": False, "message": f"User inserted successfully", "id": inserted_id})
3441

3542
@router.put("/{user_id:int}")
3643
def user_edit(
3744
user_id: int,
3845
user: UserEditSchema,
3946
perms = Depends(PermissionChecker("usuario-edit"))
4047
):
41-
return UserService().edit(user_id, user)
48+
UserService().edit(user_id, user)
49+
return JSONResponse(status_code=200, content={"error": False, "message": "User edited successfully"})
4250

4351
@router.delete("/{user_id:int}")
4452
def user_delete(
4553
user_id: int,
4654
perms = Depends(PermissionChecker("usuario-delete"))
4755
):
48-
return UserService().delete(user_id)
56+
UserService().delete(user_id)
57+
return JSONResponse(status_code=200, content={"error": False, "message": "User deleted successfully"})

src/controllers/userTypeController.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
from fastapi.responses import JSONResponse
12
from fastapi import APIRouter, Depends, Request
23

34
from ._helpers import PermissionChecker
@@ -21,30 +22,34 @@ def user_type_view(
2122
user_type_id: int,
2223
perms = Depends(PermissionChecker("tipo_usuario-view"))
2324
):
24-
response = UserTypeService().view(user_type_id)
25-
return response
25+
user_type = UserTypeService().view(user_type_id)
26+
27+
if user_type is None:
28+
return JSONResponse(status_code=404, content={"error": True, "message": f"User type with id {user_type_id} not found"})
29+
30+
return JSONResponse(status_code=200, content={"error": False, "data": user_type})
2631

2732
@router.post("/")
2833
def user_type_add(
2934
user_type: UserTypeSchema,
3035
perms = Depends(PermissionChecker("tipo_usuario-add"))
3136
):
32-
response = UserTypeService().add(user_type)
33-
return response
37+
inserted_id = UserTypeService().add(user_type)
38+
return JSONResponse(status_code=200, content={"error": False, "message": f"User type inserted successfully", "id": inserted_id})
3439

3540
@router.put("/{user_type_id:int}")
3641
def user_type_edit(
3742
user_type_id: int,
3843
user_type: UserTypeSchema,
3944
perms = Depends(PermissionChecker("tipo_usuario-edit"))
4045
):
41-
response = UserTypeService().edit(user_type_id, user_type)
42-
return response
46+
UserTypeService().edit(user_type_id, user_type)
47+
return JSONResponse(status_code=200, content={"error": False, "message": "User type edited successfully"})
4348

4449
@router.delete("/{user_type_id:int}")
4550
def user_type_delete(
4651
user_type_id: int,
4752
perms = Depends(PermissionChecker("tipo_usuario-delete"))
4853
):
49-
response = UserTypeService().delete(user_type_id)
50-
return response
54+
UserTypeService().delete(user_type_id)
55+
return JSONResponse(status_code=200, content={"error": False, "message": "User type deleted successfully"})

src/infra/database/scripts/rules.sql

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
-- Tipo Usuário
22
INSERT INTO tipo_usuario (id, nome) VALUES (1, 'admin');
3+
ALTER SEQUENCE tipo_usuario_id_seq RESTART WITH 2;
34

45
-- Usuário
56
-- senha: 1234
6-
INSERT INTO usuario (id, email, senha, tipo_usuario_id) VALUES (1, "admin@email.com", "$6$xvhoMyeu7TlurX6Z$.j4NQGAvbEzu3IKSJAWU8IzTqAGVW8RZ2sUWmJSzJY2QR0VJhm26rOC/0.7UXT3c8YrwoS3y4pUdbWJV7GEZG1", 1)
7+
INSERT INTO usuario (id, email, senha, tipo_usuario_id) VALUES (1, 'admin@email.com', '$6$xvhoMyeu7TlurX6Z$.j4NQGAvbEzu3IKSJAWU8IzTqAGVW8RZ2sUWmJSzJY2QR0VJhm26rOC/0.7UXT3c8YrwoS3y4pUdbWJV7GEZG1', 1);
8+
ALTER SEQUENCE usuario_id_seq RESTART WITH 2;
79

810
-- Controllers
911
INSERT INTO controllers (id, nome) VALUES (1, 'usuario');

src/services/userService.py

Lines changed: 15 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -45,40 +45,37 @@ def all(self, query_params: QueryParams) -> dict[str, Any]:
4545
output = paginate(query, page, rows_per_page, sort)
4646
return output
4747

48-
def view(self, user_id: int) -> dict[str, Any]:
48+
def view(self, user_id: int) -> dict[str, Any] | None:
4949
user = None
5050

5151
try:
5252
with PgDatabase() as db:
5353
db.cursor.execute(f"SELECT {self.all_columns} FROM {self.table} WHERE id = %s", (user_id,))
5454
row = db.cursor.fetchone()
55-
56-
if row is None:
57-
raise HTTPException(status_code=404, detail={"error": True, "message": "Usuário não encontrado"})
5855
except Exception:
5956
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
60-
61-
user = line_to_dict(row, self.columns)
57+
58+
if row is not None:
59+
user = line_to_dict(row, self.columns)
60+
6261
return user
63-
6462

65-
def view_by_email(self, email: str) -> dict[str, Any]:
63+
def view_by_email(self, email: str) -> dict[str, Any] | None:
6664
user = None
6765

6866
try:
6967
with PgDatabase() as db:
7068
db.cursor.execute(f"SELECT {self.all_columns} FROM {self.table} WHERE email = %s", (email,))
7169
row = db.cursor.fetchone()
72-
73-
if row is None:
74-
raise HTTPException(status_code=404, detail={"error": True, "message": "Usuário não encontrado"})
7570
except Exception:
7671
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
7772

78-
user = line_to_dict(row, self.columns)
73+
if row is not None:
74+
user = line_to_dict(row, self.columns)
75+
7976
return user
8077

81-
def add(self, user: UserAddSchema) -> dict[str, Any]:
78+
def add(self, user: UserAddSchema) -> int:
8279
senha = bcrypt_context.hash(user.senha)
8380

8481
try:
@@ -91,12 +88,14 @@ def add(self, user: UserAddSchema) -> dict[str, Any]:
9188

9289
inserted_id = raw_id[0]
9390
db.connection.commit()
91+
except HTTPException as e:
92+
raise e
9493
except Exception as e:
9594
raise HTTPException(status_code=500, detail={"error": True, "message": str(e)})
9695

97-
return {"error": False, "message": f"Usuário {user.email} adicionado com sucesso.", "id": inserted_id}
96+
return inserted_id
9897

99-
def edit(self, user_id: int, user: UserEditSchema) -> dict[str, Any]:
98+
def edit(self, user_id: int, user: UserEditSchema) -> None:
10099
user_dict = user.model_dump(exclude_none=True)
101100
if not user_dict:
102101
raise HTTPException(status_code=200, detail={"error": False, "message": f"Usuário com id {user_id} editado com sucesso."})
@@ -109,14 +108,10 @@ def edit(self, user_id: int, user: UserEditSchema) -> dict[str, Any]:
109108
except Exception:
110109
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
111110

112-
return {"error": False, "message": f"Usuário com id {user_id} editado com sucesso."}
113-
114-
def delete(self, user_id: int) -> dict[str, Any]:
111+
def delete(self, user_id: int) -> None:
115112
try:
116113
with PgDatabase() as db:
117114
db.cursor.execute(f"DELETE FROM {self.table} WHERE id = %s", (user_id,))
118115
db.connection.commit()
119116
except Exception:
120117
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
121-
122-
return {"error": False, "message": f"Usuário com id {user_id} deletado com sucesso."}

src/services/userTypeService.py

Lines changed: 10 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
from functools import reduce
21
from typing import Any
2+
from functools import reduce
33
from fastapi import HTTPException
4-
from fastapi.responses import JSONResponse
54
from psycopg2.errors import UniqueViolation
65
from fastapi.datastructures import QueryParams
76

@@ -39,26 +38,25 @@ def all(self, query_params: QueryParams) -> dict[str, Any]:
3938
if sort_order.lower() not in ["asc", "desc"]:
4039
raise HTTPException(status_code=422, detail={"error": True, "message": f"Direção de ordenação {sort_order} inválida, deve ser 'asc' ou 'desc'"})
4140

42-
output = paginate(query, page, rows_per_page, sort)
41+
output = paginate(query, page, rows_per_page, sort)
4342
return output
4443

45-
def view(self, user_type_id: int) -> dict[str, Any]:
44+
def view(self, user_type_id: int) -> dict[str, Any] | None:
4645
user_type = None
4746

4847
try:
4948
with PgDatabase() as db:
5049
db.cursor.execute(f"SELECT {self.all_columns} FROM {self.table} WHERE id = %s", (user_type_id,))
5150
row = db.cursor.fetchone()
52-
53-
if row is None:
54-
raise HTTPException(status_code=404, detail={"error": True, "message": "Tipo de usuário não encontrado"})
5551
except Exception:
5652
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
5753

58-
user_type = line_to_dict(row, self.columns)
54+
if row is not None:
55+
user_type = line_to_dict(row, self.columns)
56+
5957
return user_type
6058

61-
def add(self, user_type: UserTypeSchema) -> dict[str, Any]:
59+
def add(self, user_type: UserTypeSchema) -> int:
6260
try:
6361
with PgDatabase() as db:
6462
db.cursor.execute(f"INSERT INTO {self.table} (nome) VALUES (%s) RETURNING id", (user_type.nome,))
@@ -74,9 +72,9 @@ def add(self, user_type: UserTypeSchema) -> dict[str, Any]:
7472
except Exception:
7573
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
7674

77-
return {"error": False, "message": f"Tipo de usuário {user_type.nome} adicionado com sucesso.", "id": inserted_id}
75+
return inserted_id
7876

79-
def edit(self, user_type_id: int, user_type: UserTypeSchema) -> dict[str, Any]:
77+
def edit(self, user_type_id: int, user_type: UserTypeSchema) -> None:
8078
user_type_dict = user_type.model_dump(exclude_none=True)
8179
if not user_type_dict:
8280
raise HTTPException(status_code=200, detail={"error": False, "message": f"Tipo de usuário com id {user_type_id} editado com sucesso."})
@@ -91,14 +89,10 @@ def edit(self, user_type_id: int, user_type: UserTypeSchema) -> dict[str, Any]:
9189
except Exception as e:
9290
raise HTTPException(status_code=500, detail={"error": True, "message": str(e)})
9391

94-
return {"error": False, "message": f"Tipo de usuário com id {user_type_id} editado com sucesso."}
95-
96-
def delete(self, user_type_id: int) -> dict[str, Any]:
92+
def delete(self, user_type_id: int) -> None:
9793
try:
9894
with PgDatabase() as db:
9995
db.cursor.execute(f"DELETE FROM {self.table} WHERE id = %s", (user_type_id,))
10096
db.connection.commit()
10197
except Exception:
10298
raise HTTPException(status_code=500, detail={"error": True, "message": "Database error"})
103-
104-
return {"error": False, "message": f"Tipo de usuário com id {user_type_id} deletado com sucesso."}

src/tests/test_userType.py

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,13 @@ def create_user_type(name: str) -> dict[str, str]:
4141
return user_type
4242

4343
@pytest.fixture(scope="session")
44-
def headers():
45-
return {"Content-Type": "application/json", "accept": "application/json"}
44+
def headers(client):
45+
base_headers = {"Content-Type": "application/x-www-form-urlencoded", "accept": "application/json"}
46+
admin_user = {"username": "admin@email.com", "password": "1234"}
47+
48+
response = client.post("/auth/login", data=admin_user, headers=base_headers).json()
49+
headers = {"Content-Type": "application/json", "accept": "application/json", "Authorization": f"{response["token_type"]} {response["access_token"]}"}
50+
return headers
4651

4752
@pytest.fixture(scope="session")
4853
def client():
@@ -115,12 +120,12 @@ def test_delete_unused_user_type(client, headers):
115120
mocked_type = create_user_type("type_to_delete")
116121
mocked_id = client.post("/user/type", json=mocked_type, headers=headers).json()["id"]
117122

118-
response = client.delete(f"/user/type/{mocked_id}")
123+
response = client.delete(f"/user/type/{mocked_id}", headers=headers)
119124
assert response.status_code == 200
120125

121126
def test_delete_nonexistent_user_type(client, headers):
122127
mocked_type = create_user_type("nonexistent_user_type")
123128
mocked_id = client.post("/user/type", json=mocked_type, headers=headers).json()["id"]
124129

125-
response = client.delete(f"/user/type/{mocked_id + 1999}")
130+
response = client.delete(f"/user/type/{mocked_id + 1999}", headers=headers)
126131
assert response.status_code == 200

0 commit comments

Comments
 (0)