Skip to content

Commit

Permalink
add get_all, paTch, delete endpoints notifications
Browse files Browse the repository at this point in the history
Co-authored-by: violeta <viperez@fi.uba.ar>
  • Loading branch information
fjpacheco and violetaperezandrade committed May 6, 2024
1 parent 0b1428d commit 3b74877
Show file tree
Hide file tree
Showing 6 changed files with 167 additions and 22 deletions.
55 changes: 47 additions & 8 deletions app/controller/Users.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,15 +66,54 @@ async def handle_login(self, auth_code: str):

def handle_update_user(self, update_data: dict, user_id: int):
self.users_service.update_user(user_id, update_data)
return {
"message": "User updated successfully",
"status": status.HTTP_200_OK,
}
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": "User updated successfully",
"status": status.HTTP_200_OK,
}),
)

def handle_create_notification(self, notification_data: dict,
user_id: int):
self.users_service.create_notification(user_id, notification_data)
return {
"message": "Notification created successfully",
"status": status.HTTP_201_CREATED,
}
return JSONResponse(
status_code=status.HTTP_201_CREATED,
content=jsonable_encoder({
"message": "Notification created successfully",
"status": status.HTTP_201_CREATED,
}),
)

def handle_get_notifications(self, user_id: int):
notifications = self.users_service.get_notifications(user_id)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": notifications,
"status": status.HTTP_200_OK,
}),
)

def handle_delete_notification(self, user_id: int, notification_id: int):
self.users_service.delete_notification(user_id,
notification_id)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": "Notification deleted successfully",
"status": status.HTTP_200_OK,
})
)

def handle_update_notification(self, user_id: int, notification_id: int,
update_data: dict):
self.users_service.update_notification(user_id, notification_id,
update_data)
return JSONResponse(
status_code=status.HTTP_200_OK,
content=jsonable_encoder({
"message": "Notification updated successfully",
"status": status.HTTP_200_OK,
}),
)
6 changes: 3 additions & 3 deletions app/exceptions/UserException.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
from fastapi import HTTPException, status


class UserNotFound(HTTPException):
def __init__(self, id: int):
class ResourceNotFound(HTTPException):
def __init__(self, id: int, resource: str = "Resource"):
status_code = status.HTTP_404_NOT_FOUND
detail = f"User with id {id} not found"
detail = f"{resource} with id {id} not found"
super().__init__(status_code=status_code, detail=detail)


Expand Down
53 changes: 44 additions & 9 deletions app/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,51 +7,57 @@
CreateUserSchema,
UpdateUserSchema,
LoginRequest,
CreateNotificationSchema
CreateNotificationSchema,
UpdateNotificationSchema
)
from security.JWTBearer import get_current_user_id
from logs import init_logging
logger = init_logging('user-repository')

app = FastAPI()
app = FastAPI(
title="Users API",
version="0.1.0",
summary="Microservice for users management",
)

users_repository = UsersRepository()
users_service = UsersService(users_repository)
users_controller = UsersController(users_service)


@app.get("/")
@app.get("/", tags=["Healthcheck"])
def root():
return {"message": "users service"}


@app.get("/users/me")
@app.get("/users/me", tags=["Users"])
def get_users(user_id: Annotated[int, Depends(get_current_user_id)]):
return users_controller.handle_get_user(user_id)


@app.get("/users")
@app.get("/users", tags=["Users"])
def get_all_users(_: Annotated[int, Depends(get_current_user_id)],
ids: Annotated[Union[List[str], None], Query()] = None):
return users_controller.handle_get_all_users(ids)


@app.post("/users")
@app.post("/users", tags=["Users"])
async def create_user(user_data: CreateUserSchema):
return await users_controller.handle_create_user(user_data.dict())


@app.post("/login")
@app.post("/login", tags=["Auth"])
async def login_with_google(request: LoginRequest):
return await users_controller.handle_login(request.auth_code)


@app.patch("/users/me")
@app.patch("/users/me", tags=["Users"])
async def update_user(update_data: UpdateUserSchema,
user_id: Annotated[int, Depends(get_current_user_id)]):
return users_controller.handle_update_user(update_data.dict(), user_id)


@app.post("/users/me/notification")
@app.post("/users/me/notification", tags=["Notifications"])
async def create_notification(
user_id: Annotated[int,
Depends(get_current_user_id)],
Expand All @@ -60,3 +66,32 @@ async def create_notification(
logger.info(f"Creating notification for user {user_id}")
return users_controller.handle_create_notification(
create_notification.dict(), user_id)


@app.get("/users/me/notifications", tags=["Notifications"])
async def get_my_notifications(user_id: Annotated[
int,
Depends(get_current_user_id)]):
return users_controller.handle_get_notifications(user_id)


@app.delete("/users/me/notifications/{notification_id}",
tags=["Notifications"])
async def delete_notification(user_id: Annotated[
int,
Depends(get_current_user_id)],
notification_id: int):
return users_controller.handle_delete_notification(user_id,
notification_id)


@app.patch("/users/me/notifications/{notification_id}",
tags=["Notifications"])
async def update_notification(user_id: Annotated[
int,
Depends(get_current_user_id)],
notification_id: int,
update_data: UpdateNotificationSchema):
return users_controller.handle_update_notification(user_id,
notification_id,
update_data.dict())
28 changes: 28 additions & 0 deletions app/repository/Users.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,34 @@ def create_notification(self, user_id: int, notification_data: dict):
self.session.commit()
return alarm

@withSQLExceptionsHandle()
def get_notification_owner(self, notification_id):
alarm = self.session.query(Alarm).filter_by(
id=notification_id).first()
return alarm.id_user if alarm else None

@withSQLExceptionsHandle()
def edit_notification(self, notification_id, update_data):
alarm = self.session.query(Alarm).filter_by(
id=notification_id).first()
for field, value in update_data.items():
setattr(alarm, field, value)

self.session.commit()
return alarm

@withSQLExceptionsHandle()
def get_notifications(self, user_id: int):
alarm = self.session.query(Alarm).filter_by(id_user=user_id).all()
return self.__parse_result(alarm)

@withSQLExceptionsHandle()
def delete_notification(self, notification_id):
alarm = self.session.query(Alarm).filter_by(
id=notification_id).first()
self.session.delete(alarm)
self.session.commit()

@withSQLExceptionsHandle()
def get_users_to_notify(self,
date_time: datetime) -> list[tuple[int,
Expand Down
11 changes: 11 additions & 0 deletions app/schemas/Schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,3 +52,14 @@ def validate_date_time(cls, v):
if v.minute % 5 != 0:
raise ValueError('Minutes must be multiples of 5')
return v


class UpdateNotificationSchema(BaseModel):
date_time: Optional[datetime] = Field(..., alias='date_time')
content: Optional[str] = Field(..., max_length=128)

@validator('date_time')
def validate_date_time(cls, v):
if v.minute % 5 != 0:
raise ValueError('Minutes must be multiples of 5')
return v
36 changes: 34 additions & 2 deletions app/service/Users.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from exceptions.UserException import UserNotFound, InvalidData, InvalidURL
from exceptions.UserException import ResourceNotFound, InvalidData, InvalidURL
from exceptions.LoginException import AuthenticationError
from exceptions.UserException import ForbiddenUser
from models.users import User
from repository.Users import UsersRepository
import requests
Expand All @@ -18,7 +19,7 @@ def __init__(self, user_repository: UsersRepository):
def get_user(self, user_id: int):
user = self.user_repository.get_user(user_id)
if not user:
raise UserNotFound(user_id)
raise ResourceNotFound(user_id, "User")
return user

def get_all_users(self):
Expand Down Expand Up @@ -60,6 +61,37 @@ def create_notification(self, user_id: int, notification_data: dict):
self.user_repository.rollback()
raise e

def get_notifications(self, user_id: int):
return self.user_repository.get_notifications(user_id)

def update_notification(self, user_id: int, notification_id: int,
update_data: dict):
notification_owner = self.user_repository.\
get_notification_owner(notification_id)
if user_id != notification_owner:
raise ForbiddenUser()
try:
self.user_repository.edit_notification(notification_id,
update_data)
except Exception as e:
self.user_repository.rollback()
raise e

def delete_notification(self, user_id: int, notification_id: int):
notification_owner = self.user_repository.\
get_notification_owner(notification_id)

if notification_owner is None:
raise ResourceNotFound(notification_id, "Notification")

if user_id != notification_owner:
raise ForbiddenUser()
try:
self.user_repository.delete_notification(notification_id)
except Exception as e:
self.user_repository.rollback()
raise e

def _generate_nickname(self, name):

name_without_spaces = name.replace(" ", "")
Expand Down

0 comments on commit 3b74877

Please sign in to comment.