From ae2ce859ad38467919902620c3a48c3dc36d4091 Mon Sep 17 00:00:00 2001 From: Daniel Schick Date: Sun, 16 Nov 2025 19:26:15 +0100 Subject: [PATCH] Do not accidentally overwrite shipcall fields when fields are not passed on PUT request --- src/server/BreCal/api/shipcalls.py | 2 +- src/server/BreCal/impl/shipcalls.py | 36 +++++++++++++++++------------ 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/src/server/BreCal/api/shipcalls.py b/src/server/BreCal/api/shipcalls.py index 1f3f0c3..a4e1045 100644 --- a/src/server/BreCal/api/shipcalls.py +++ b/src/server/BreCal/api/shipcalls.py @@ -89,7 +89,7 @@ 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) + return impl.shipcalls.PutShipcalls(loadedModel, content) except ValidationError as ex: return create_validation_error_response(ex=ex, status_code=400) diff --git a/src/server/BreCal/impl/shipcalls.py b/src/server/BreCal/impl/shipcalls.py index fbb7eef..0eb226b 100644 --- a/src/server/BreCal/impl/shipcalls.py +++ b/src/server/BreCal/impl/shipcalls.py @@ -185,7 +185,7 @@ def PostShipcalls(schemaModel): pooledConnection.close() -def PutShipcalls(schemaModel): +def PutShipcalls(schemaModel, original_payload=None): """ :param schemaModel: The deserialized dict of the request @@ -209,10 +209,12 @@ def PutShipcalls(schemaModel): was_canceled = theshipcall["canceled"] - # query = SQLQuery.get_shipcall_put(schemaModel) - query = "UPDATE shipcall SET " - isNotFirst = False + provided_keys = set(original_payload.keys()) if isinstance(original_payload, dict) else None + + update_clauses = [] for key in schemaModel.keys(): + if provided_keys is not None and key not in provided_keys: + continue param_key = key if key == "id": continue @@ -234,19 +236,19 @@ def PutShipcalls(schemaModel): param_key = "evaluation_value" if key == "evaluation_value": continue - if isNotFirst: - query += ", " - isNotFirst = True - query += key + " = ?" + param_key + "? " + update_clauses.append(f"{key} = ?{param_key}?") - query += "WHERE id = ?id?" + if update_clauses: + query = "UPDATE shipcall SET " + ", ".join(update_clauses) + " WHERE id = ?id?" + commands.execute(query, param=schemaModel) - affected_rows = commands.execute(query, param=schemaModel) + ship_id_value = schemaModel.get("ship_id") if (provided_keys is None or "ship_id" in provided_keys) else theshipcall["ship_id"] - shipdata = get_ship_data_for_id(schemaModel["ship_id"]) + shipdata = get_ship_data_for_id(ship_id_value) message = shipdata['name'] - if "type_value" in schemaModel: - match schemaModel["type_value"]: + type_value = schemaModel.get("type_value") if (provided_keys is None or "type" in provided_keys) else theshipcall["type"] + if type_value is not None: + match type_value: case 1: message += " [ARRIVAL]" case 2: @@ -258,6 +260,9 @@ def PutShipcalls(schemaModel): pquery = "SELECT id, participant_id, type FROM shipcall_participant_map where shipcall_id = ?id?" pdata = commands.query(pquery,param={"id" : schemaModel["id"]}) # existing list of assignments + if schemaModel.get("participants") is None: + schemaModel["participants"] = [] + # loop across passed participant ids, creating entries for those not present in pdata existing_notifications = get_notification_for_shipcall_and_type(schemaModel["id"], 1) # type = 1 is assignment @@ -306,8 +311,9 @@ def PutShipcalls(schemaModel): commands.execute(nquery, param={"shipcall_id" : schemaModel["id"], "participant_id" : elem["participant_id"], "message" : message}) break - if schemaModel["canceled"] is not None: - if schemaModel["canceled"] and not was_canceled: + canceled_value = schemaModel.get("canceled") + if canceled_value is not None: + if canceled_value and not was_canceled: # create a canceled notification for all currently assigned participants stornoNotificationQuery = "INSERT INTO notification (shipcall_id, participant_id, level, type, message) VALUES (?shipcall_id?, ?participant_id?, 0, 7, ?message?)" for participant_assignment in schemaModel["participants"]: