Skip to content

Commit

Permalink
implement auth service
Browse files Browse the repository at this point in the history
  • Loading branch information
violetaperezandrade committed Apr 19, 2024
1 parent 4236140 commit f1968bb
Show file tree
Hide file tree
Showing 5 changed files with 70 additions and 10 deletions.
12 changes: 9 additions & 3 deletions app/controller/Users.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
from fastapi import status
from fastapi import status, Request
from fastapi.encoders import jsonable_encoder
from fastapi.responses import JSONResponse
from service.Users import UsersService
from service.Auth import AuthService


class UsersController:
def __init__(self, users_service: UsersService):
def __init__(self, users_service: UsersService,
auth_service: AuthService):
self.users_service = users_service
self.auth_service = auth_service

def handle_get_user(self, user_id: int):
user = self.users_service.get_user(user_id)
Expand Down Expand Up @@ -51,7 +54,10 @@ def handle_login(self, auth_code: str):
},
)

def handle_update_user(self, user_id: int, update_data: dict):
def handle_update_user(self, user_id: int,
update_data: dict,
request: Request):
self.auth_service.authenticate(user_id, request)
self.users_service.update_user(user_id, update_data)
return {
"message": "User updated successfully",
Expand Down
14 changes: 14 additions & 0 deletions app/exceptions/UserException.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ def __init__(self, id: int):
status_code = status.HTTP_400_BAD_REQUEST
detail = "Invalid URL"
super().__init__(status_code=status_code, detail=detail)


class ForbiddenUser(HTTPException):
def __init__(self):
status_code = status.HTTP_403_FORBIDDEN
detail = "User is not authorized"
super().__init__(status_code=status_code, detail=detail)


class UnauthorizedUser(HTTPException):
def __init__(self):
status_code = status.HTTP_401_UNAUTHORIZED
detail = "Invalid credentials"
super().__init__(status_code=status_code, detail=detail)
13 changes: 9 additions & 4 deletions app/main.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
from fastapi import FastAPI
from fastapi import FastAPI, Request
from controller.Users import UsersController
from service.Users import UsersService
from service.Auth import AuthService
from repository.Users import UsersRepository
from schemas.Schemas import CreateUserSchema, UpdateUserSchema
from schemas.Schemas import LoginRequest


app = FastAPI()
users_repository = UsersRepository()
auth_service = AuthService()
users_service = UsersService(users_repository)
users_controller = UsersController(users_service)
users_controller = UsersController(users_service, auth_service)


@app.get("/")
Expand Down Expand Up @@ -38,5 +40,8 @@ def login_with_google(request: LoginRequest):


@app.patch("/users/{user_id}")
async def update_user(user_id: int, update_data: UpdateUserSchema):
return users_controller.handle_update_user(user_id, update_data.dict())
async def update_user(user_id: int, update_data: UpdateUserSchema,
request: Request):
return users_controller.handle_update_user(user_id,
update_data.dict(),
request)
38 changes: 38 additions & 0 deletions app/service/Auth.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import jwt
import os
from exceptions.UserException import ForbiddenUser, UnauthorizedUser


TOKEN_FIELD_NAME = "x-access-token"


class AuthService():
def __init__(self):
self.__secret = os.environ.get("JWT_SECRET")

def authenticate(self, user_id: int, request):
token = self._get_token(request.headers)
if not token:
raise UnauthorizedUser()
try:
payload = jwt.decode(token, self.__secret, algorithms=["HS256"])

except jwt.ExpiredSignatureError:
raise UnauthorizedUser()

except jwt.InvalidTokenError:
raise UnauthorizedUser()

if payload.get("user_id") != user_id:
raise ForbiddenUser()

return

def _get_token(self, headers: dict):
keyName = None
for key in headers.keys():
if key.lower() == TOKEN_FIELD_NAME:
keyName = key
if not keyName:
return None
return headers.get(keyName)
3 changes: 0 additions & 3 deletions app/service/Users.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,6 @@ def create_user(self, user_data: dict):
return self.user_repository.create_user(**user_data)

def update_user(self, user_id: int, update_data: dict):
# TODO: aca habria que chequear a partir del token, session o algo que
# es el propio usuario editando sus datos y no permitir
# que un usuario edite los de un tercero
self.get_user(user_id)
filtered_update_data = {k: v for k, v in update_data.items()
if v is not None}
Expand Down

0 comments on commit f1968bb

Please sign in to comment.