diff --git a/src/server/BreCal/api/berths.py b/src/server/BreCal/api/berths.py index 57d960e..114f893 100644 --- a/src/server/BreCal/api/berths.py +++ b/src/server/BreCal/api/berths.py @@ -1,3 +1,4 @@ +import logging from flask import Blueprint, request from webargs.flaskparser import parser from .. import impl @@ -12,8 +13,12 @@ bp = Blueprint('berths', __name__) @auth_guard() # no restriction by role def GetBerths(): - if 'Authorization' in request.headers: - token = request.headers.get('Authorization') - return impl.berths.GetBerths(token) - else: - return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + try: + if 'Authorization' in request.headers: + token = request.headers.get('Authorization') + return impl.berths.GetBerths(token) + else: + return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) diff --git a/src/server/BreCal/api/history.py b/src/server/BreCal/api/history.py index 1cf99e4..098423f 100644 --- a/src/server/BreCal/api/history.py +++ b/src/server/BreCal/api/history.py @@ -1,3 +1,4 @@ +import logging from flask import Blueprint, request from .. import impl from ..services.auth_guard import auth_guard @@ -10,13 +11,16 @@ bp = Blueprint('history', __name__) @auth_guard() # no restriction by role def GetHistory(): - if 'Authorization' in request.headers: - token = request.headers.get('Authorization') - options = {} - if not 'shipcall_id' in request.args: - return create_dynamic_exception_response(ex=None, status_code=400, message="missing parameter: shipcall_id") - options["shipcall_id"] = request.args.get("shipcall_id") - return impl.history.GetHistory(options) - else: - return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + try: + if 'Authorization' in request.headers: + token = request.headers.get('Authorization') + options = {} + if not 'shipcall_id' in request.args: + return create_dynamic_exception_response(ex=None, status_code=400, message="missing parameter: shipcall_id") + options["shipcall_id"] = request.args.get("shipcall_id") + return impl.history.GetHistory(options) + else: + return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) diff --git a/src/server/BreCal/api/notifications.py b/src/server/BreCal/api/notifications.py index b68a75f..4fe4a8e 100644 --- a/src/server/BreCal/api/notifications.py +++ b/src/server/BreCal/api/notifications.py @@ -11,10 +11,13 @@ bp = Blueprint('notifications', __name__) @bp.route('/notifications', methods=['get']) @auth_guard() # no restriction by role def GetNotifications(): - if 'shipcall_id' in request.args: - options = {} - options["shipcall_id"] = request.args.get("shipcall_id") - return impl.notifications.GetNotifications(options) - else: - logging.warning("attempt to load notifications without shipcall id") - return create_dynamic_exception_response(ex=None, status_code=400, message="missing argument: shipcall_id") + try: + if 'shipcall_id' in request.args: + options = {} + options["shipcall_id"] = request.args.get("shipcall_id") + return impl.notifications.GetNotifications(options) + else: + return create_dynamic_exception_response(ex=None, status_code=400, message="missing argument: shipcall_id") + + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) diff --git a/src/server/BreCal/api/participant.py b/src/server/BreCal/api/participant.py index 53a369f..814a3dd 100644 --- a/src/server/BreCal/api/participant.py +++ b/src/server/BreCal/api/participant.py @@ -1,3 +1,4 @@ +import logging from flask import Blueprint, request from .. import impl from ..services.auth_guard import auth_guard @@ -10,11 +11,14 @@ bp = Blueprint('participants', __name__) @auth_guard() # no restriction by role def GetParticipant(): - if 'Authorization' in request.headers: - token = request.headers.get('Authorization') - options = {} - options["user_id"] = request.args.get("user_id") - return impl.participant.GetParticipant(options) - else: - return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + try: + if 'Authorization' in request.headers: + token = request.headers.get('Authorization') + options = {} + options["user_id"] = request.args.get("user_id") + return impl.participant.GetParticipant(options) + else: + return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) diff --git a/src/server/BreCal/api/shipcalls.py b/src/server/BreCal/api/shipcalls.py index 743c85b..b21908e 100644 --- a/src/server/BreCal/api/shipcalls.py +++ b/src/server/BreCal/api/shipcalls.py @@ -20,24 +20,28 @@ bp = Blueprint('shipcalls', __name__) @bp.route('/shipcalls', methods=['get']) @auth_guard() # no restriction by role def GetShipcalls(): - if 'Authorization' in request.headers: - token = request.headers.get('Authorization') # see impl/login to see the token encoding, which is a JWT token. + try: + if 'Authorization' in request.headers: + token = request.headers.get('Authorization') # see impl/login to see the token encoding, which is a JWT token. - """ - from BreCal.services.jwt_handler import decode_jwt - jwt = token.split('Bearer ')[1] # string key - payload = decode_jwt(jwt) # dictionary, which includes 'id' (user id) and 'participant_id' + """ + from BreCal.services.jwt_handler import decode_jwt + jwt = token.split('Bearer ')[1] # string key + payload = decode_jwt(jwt) # dictionary, which includes 'id' (user id) and 'participant_id' - # oneline: - payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1]) - """ - options = {} - options["participant_id"] = request.args.get("participant_id") - options["past_days"] = request.args.get("past_days", default=1, type=int) + # oneline: + payload = decode_jwt(request.headers.get("Authorization").split("Bearer ")[-1]) + """ + options = {} + options["participant_id"] = request.args.get("participant_id") + options["past_days"] = request.args.get("past_days", default=1, type=int) - return impl.shipcalls.GetShipcalls(options) - else: - return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + return impl.shipcalls.GetShipcalls(options) + else: + return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) @bp.route('/shipcalls', methods=['post']) @@ -55,20 +59,15 @@ def PostShipcalls(): # validate the posted shipcall data & the user's authority InputValidationShipcall.evaluate_post_data(user_data, loadedModel, content) + return impl.shipcalls.PostShipcalls(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) logging.error(traceback.format_exc()) - print(ex) return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") - return impl.shipcalls.PostShipcalls(loadedModel) - @bp.route('/shipcalls', methods=['put']) @auth_guard() # no restriction by role @@ -85,20 +84,15 @@ def PutShipcalls(): # validate the PUT shipcall data and the user's authority InputValidationShipcall.evaluate_put_data(user_data, loadedModel, content) + return impl.shipcalls.PutShipcalls(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except werkzeug.exceptions.Forbidden as ex: - logging.error(ex) - print(ex) return create_werkzeug_error_response(ex=ex, status_code=403) except Exception as ex: - logging.error(ex) - print(ex) - return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") + logging.error(traceback.format_exc()) + return create_dynamic_exception_response(ex=None, status_code=400, message="bad format") - return impl.shipcalls.PutShipcalls(loadedModel) diff --git a/src/server/BreCal/api/ships.py b/src/server/BreCal/api/ships.py index 9237502..9e92ffa 100644 --- a/src/server/BreCal/api/ships.py +++ b/src/server/BreCal/api/ships.py @@ -17,11 +17,15 @@ bp = Blueprint('ships', __name__) @auth_guard() # no restriction by role def GetShips(): - if 'Authorization' in request.headers: - token = request.headers.get('Authorization') - return impl.ships.GetShips(token) - else: - return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + try: + if 'Authorization' in request.headers: + token = request.headers.get('Authorization') + return impl.ships.GetShips(token) + else: + return create_dynamic_exception_response(ex=None, status_code=403, message="not authenticated") + + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) @bp.route('/ships', methods=['post']) @@ -45,19 +49,14 @@ def PostShip(): # validate the request data & user permissions InputValidationShip.evaluate_post_data(user_data, loadedModel, content) + return impl.ships.PostShip(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) return create_dynamic_exception_response(ex=ex, status_code=400, message=None) - return impl.ships.PostShip(loadedModel) - @bp.route('/ships', methods=['put']) @auth_guard() # no restriction by role @@ -74,18 +73,13 @@ def PutShip(): # validate the request data & user permissions InputValidationShip.evaluate_put_data(user_data, loadedModel, content) + return impl.ships.PutShip(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) - return create_dynamic_exception_response(ex=ex, status_code=400, message=None) - - return impl.ships.PutShip(loadedModel) + return create_dynamic_exception_response(ex=ex, status_code=400) @bp.route('/ships', methods=['delete']) @@ -107,15 +101,11 @@ def DeleteShip(): # validate the request data & user permissions InputValidationShip.evaluate_delete_data(user_data, ship_id) + return impl.ships.DeleteShip(options) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) - return create_dynamic_exception_response(ex=ex, status_code=400, message=None) + return create_dynamic_exception_response(ex=ex, status_code=400) - return impl.ships.DeleteShip(options) diff --git a/src/server/BreCal/api/times.py b/src/server/BreCal/api/times.py index 5bf3626..ff8e17e 100644 --- a/src/server/BreCal/api/times.py +++ b/src/server/BreCal/api/times.py @@ -16,10 +16,13 @@ bp = Blueprint('times', __name__) @auth_guard() # no restriction by role def GetTimes(): - options = {} - options["shipcall_id"] = request.args.get("shipcall_id") - - return impl.times.GetTimes(options) + try: + options = {} + options["shipcall_id"] = request.args.get("shipcall_id") + return impl.times.GetTimes(options) + + except Exception as ex: + return create_dynamic_exception_response(ex=ex, status_code=400) @bp.route('/times', methods=['post']) @@ -41,18 +44,14 @@ def PostTimes(): # validate the request InputValidationTimes.evaluate_post_data(user_data, loadedModel, content) - + return impl.times.PostTimes(loadedModel) + except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") - return impl.times.PostTimes(loadedModel) @bp.route('/times', methods=['put']) @@ -70,18 +69,14 @@ def PutTimes(): # validate the request InputValidationTimes.evaluate_put_data(user_data, loadedModel, content) + return impl.times.PutTimes(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") - return impl.times.PutTimes(loadedModel) @bp.route('/times', methods=['delete']) @@ -101,15 +96,10 @@ def DeleteTimes(): return impl.times.DeleteTimes(options) else: - logging.warning("Times delete missing id argument") - return create_dynamic_exception_response(ex=None, status_code=400, message="missing argument: id") + return create_dynamic_exception_response(ex=None, status_code=400, message="Times delete missing argument: id") except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") diff --git a/src/server/BreCal/api/user.py b/src/server/BreCal/api/user.py index 86b992b..b77c12c 100644 --- a/src/server/BreCal/api/user.py +++ b/src/server/BreCal/api/user.py @@ -19,16 +19,12 @@ def PutUser(): content = request.get_json(force=True) loadedModel = model.UserSchema().load(data=content, many=False, partial=True) + return impl.user.PutUser(loadedModel) except ValidationError as ex: - logging.error(ex) - print(ex) return create_validation_error_response(ex=ex, status_code=400) except Exception as ex: - logging.error(ex) - print(ex) - return create_dynamic_exception_response(ex=ex, status_code=400, message="bad format") + return create_dynamic_exception_response(ex=None, status_code=400, message="bad format") - return impl.user.PutUser(loadedModel) diff --git a/src/server/BreCal/validators/validation_error.py b/src/server/BreCal/validators/validation_error.py index b9b2059..36f5cc8 100644 --- a/src/server/BreCal/validators/validation_error.py +++ b/src/server/BreCal/validators/validation_error.py @@ -15,7 +15,7 @@ def create_default_error_format(error_description): return json_response -def create_validation_error_response(ex:ValidationError, status_code:int=400)->typing.Tuple[str,int]: +def create_validation_error_response(ex:ValidationError, status_code:int=400, create_log:bool=True)->typing.Tuple[str,int]: # generate an overview the errors #example: # {'lock_time': ['The provided value must be in the future. Current Time: 2024-09-02 08:23:32.600791, Value: 2024-09-01 08:20:41.853000']} @@ -46,8 +46,8 @@ def create_validation_error_response(ex:ValidationError, status_code:int=400)->t # } valid_data = ex.valid_data - - json_response = create_default_error_format(error_description="ValidationError") + message = "ValidationError" + json_response = create_default_error_format(error_description=message) json_response.update({ "errors":errors, "valid_data":valid_data @@ -56,18 +56,31 @@ def create_validation_error_response(ex:ValidationError, status_code:int=400)->t # json.dumps with default=str automatically converts non-serializable values to strings. Hence, datetime objects (which are not) # natively serializable are properly serialized. serialized_response = json.dumps(json_response, default=str) + + if create_log: + logging.warning(ex) if ex is not None else logging.warning(message) + print(ex) if ex is not None else print(message) return (serialized_response, status_code) -def create_werkzeug_error_response(ex:Forbidden, status_code:int=403)->typing.Tuple[str,int]: +def create_werkzeug_error_response(ex:Forbidden, status_code:int=403, create_log:bool=True)->typing.Tuple[str,int]: # json.dumps with default=str automatically converts non-serializable values to strings. Hence, datetime objects (which are not) # natively serializable are properly serialized. - json_response = create_default_error_format(error_description=ex.description) + message = ex.description + json_response = create_default_error_format(error_description=message) serialized_response = json.dumps(json_response, default=str) + + if create_log: + logging.warning(ex) if ex is not None else logging.warning(message) + print(ex) if ex is not None else print(message) return serialized_response, status_code -def create_dynamic_exception_response(ex, status_code:int=400, message:typing.Optional[str]=None): +def create_dynamic_exception_response(ex, status_code:int=400, message:typing.Optional[str]=None, create_log:bool=True): message = repr(ex) if message is None else message json_response = create_default_error_format(error_description=message) serialized_response = json.dumps(json_response, default=str) + + if create_log: + logging.warning(ex) if ex is not None else logging.warning(message) + print(ex) if ex is not None else print(message) return (serialized_response, status_code)