diff --git a/controllers/v2/unavailability/api.py b/controllers/v2/unavailability/api.py index e876e6d9..ef01ed6b 100644 --- a/controllers/v2/unavailability/api.py +++ b/controllers/v2/unavailability/api.py @@ -1,11 +1,12 @@ from flask_restful import reqparse, Resource, marshal_with, inputs from .response_models import volunteer_unavailability_time -from domain import UserType +from domain import UserType, session_scope from repository.volunteer_unavailability_v2 import EventRepository from services.jwk import requires_auth, is_user_or_has_role from controllers.v2.v2_blueprint import v2_api - +import logging +from exception import EventNotFoundError, InvalidArgumentError edit_parser = reqparse.RequestParser() edit_parser.add_argument("title", type=str) edit_parser.add_argument("start", type=inputs.datetime_from_iso8601) @@ -22,14 +23,21 @@ def __init__(self, event_repository: EventRepository = EventRepository()): @requires_auth @is_user_or_has_role(None, UserType.ROOT_ADMIN) def put(self, user_id, event_id): - args = edit_parser.parse_args() - success = self.event_repository.edit_event(user_id, event_id, **args) - if success is True: + try: + with session_scope() as session: + args = edit_parser.parse_args() + self.event_repository.edit_event(session, user_id, event_id, **args) return {"message": "Updated successfully"}, 200 - elif success is False: - return {"message": "Event not found"}, 404 - else: - return {"message": "Unexpected Error Occurred"}, 400 + except InvalidArgumentError as argumentException: + logging.warning(argumentException) + return {"message": "Invalid argument from the payload"}, 400 + except EventNotFoundError as notFoundError: + logging.warning(notFoundError) + return {"message": f"Event {event_id} can not be found"}, 404 + except Exception as ex: + logging.error(ex) + return {"message": "Unexpected error happened within the database"}, 500 + @requires_auth @is_user_or_has_role(None, UserType.ROOT_ADMIN) diff --git a/exception/__init__.py b/exception/__init__.py new file mode 100644 index 00000000..fd6bb24f --- /dev/null +++ b/exception/__init__.py @@ -0,0 +1,2 @@ +from .client_exception import EventNotFoundError, InvalidArgumentError + diff --git a/exception/client_exception.py b/exception/client_exception.py new file mode 100644 index 00000000..8b4d0acb --- /dev/null +++ b/exception/client_exception.py @@ -0,0 +1,20 @@ +from .fireapp_exception import FireAppException + + +class EventNotFoundError(FireAppException): + def __init__(self, event_id, *args): + super().__init__(f"Event not found", *args) + self.event_id = event_id + + def __str__(self): + # Optionally customize the string representation for this specific error + return f"{self.message}: Event ID {self.event_id} could not be located." + + +class InvalidArgumentError(FireAppException): + def __init__(self, *args): + super().__init__(f"Invalid argument(s)", *args) + + def __str__(self): + # Optionally customize the string representation for this specific error + return f"{self.message}: unexpected values in the payload" diff --git a/exception/database_exception.py b/exception/database_exception.py new file mode 100644 index 00000000..e69de29b diff --git a/exception/fireapp_exception.py b/exception/fireapp_exception.py new file mode 100644 index 00000000..f1a99c1c --- /dev/null +++ b/exception/fireapp_exception.py @@ -0,0 +1,3 @@ +class FireAppException(Exception): + pass + diff --git a/repository/volunteer_unavailability_v2.py b/repository/volunteer_unavailability_v2.py index b36cc0fd..1f011ed6 100644 --- a/repository/volunteer_unavailability_v2.py +++ b/repository/volunteer_unavailability_v2.py @@ -2,37 +2,36 @@ from flask import jsonify -from datetime import datetime - +from datetime import datetime, timezone +from exception import EventNotFoundError, InvalidArgumentError from domain import UnavailabilityTime, session_scope - class EventRepository: def __init__(self): pass - def edit_event(self, userId, eventId, title=None, start=None, end=None, periodicity=None): - with session_scope() as session: - try: - event = session.query(UnavailabilityTime).filter(UnavailabilityTime.eventId == eventId, - UnavailabilityTime.userId == userId).first() - if event is None: - return False - if title is not None: - event.title = title - if start is not None: - event.start = start - if end is not None: - event.end = end - if end is not None: - event.periodicity = periodicity - session.commit() - return True - except Exception as e: - session.rollback() - logging.error(e) - return None + def edit_event(self, session, userId, eventId, title=None, start=None, end=None, periodicity=None): + now = datetime.now(timezone.utc) + event = session.query(UnavailabilityTime).filter(UnavailabilityTime.eventId == eventId, + UnavailabilityTime.userId == userId).first() + if event is None: + raise EventNotFoundError(eventId) + # validate user input + if start is not None and start < now: + raise InvalidArgumentError() + if end is not None and (end < now or end < start): + raise InvalidArgumentError() + # Edit fields with new values + if title is not None: + event.title = title + if start is not None: + event.start = start + if end is not None: + event.end = end + if end is not None: + event.periodicity = periodicity + session.commit() def get_event(self, userId): """ @@ -121,4 +120,4 @@ def check_overlapping_events(self, userId, startTime, endTime, periodicity): # Add any other attributes you need }) - return overlapping_details \ No newline at end of file + return overlapping_details