From 6d8b86280c8362718897cb12446cc603f1015f41 Mon Sep 17 00:00:00 2001 From: Daniel Schick Date: Tue, 30 Sep 2025 14:46:34 +0200 Subject: [PATCH 1/2] changed e-mail formatting to direct url at actual notified shipcall --- src/server/BreCal/msg/msg_types.json | 7 ------- src/server/BreCal/services/schedule_routines.py | 3 ++- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src/server/BreCal/msg/msg_types.json b/src/server/BreCal/msg/msg_types.json index 9664605..4398615 100644 --- a/src/server/BreCal/msg/msg_types.json +++ b/src/server/BreCal/msg/msg_types.json @@ -3,49 +3,42 @@ "type" : 1, "color" : "#0867ec", "name" : "assignment", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Nominierung" }, { "type" : 2, "color" : "#ea5c00", "name" : "next24h", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Morgenrunde relevant" }, { "type" : 3, "color" : "#f34336", "name" : "time_conflict", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Zeitlicher Konflikt" }, { "type" : 4, "color" : "#28b532", "name" : "time_conflict_resolved", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Zeitlicher Konflikt gelöst" }, { "type" : 5, "color" : "#a8a8a8", "name" : "unassigned", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Nominierung abgewählt" }, { "type" : 6, "color" : "#a8a800", "name" : "missing_data", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Fehlende Daten" }, { "type" : 7, "color" : "#808070", "name" : "cancelled", - "link" : "https://www.bremen-calling.de/", "msg_text" : "Storno" } ] \ No newline at end of file diff --git a/src/server/BreCal/services/schedule_routines.py b/src/server/BreCal/services/schedule_routines.py index a86bbe3..8851444 100644 --- a/src/server/BreCal/services/schedule_routines.py +++ b/src/server/BreCal/services/schedule_routines.py @@ -135,7 +135,8 @@ def SendEmails(email_dict): with open(os.path.join(current_path,'../msg/notification_element.html'), mode="r", encoding="utf-8") as file: element = file.read() element = element.replace("[[color]]", message_type["color"]) - element = element.replace("[[link]]", message_type["link"]) + linktext = defs.email_credentials["url_template"] + str(notification.shipcall_id) + element = element.replace("[[link]]", linktext) # We want to show the following information for each notification: # Ship-name, Arr/Dep/Shift, ETA/ETD, berth From c6954fb2221f083b1dd765dbc3176baf8798a339 Mon Sep 17 00:00:00 2001 From: Daniel Schick Date: Tue, 7 Oct 2025 12:01:57 +0200 Subject: [PATCH 2/2] Fixed some validation issues that have cropped up over the last months --- .../validators/input_validation_base.py | 31 +++++++++++++++++++ .../validators/input_validation_ship.py | 20 +++++++++++- .../validators/input_validation_shipcall.py | 9 ++++-- .../validators/input_validation_times.py | 7 ++++- 4 files changed, 63 insertions(+), 4 deletions(-) create mode 100644 src/server/BreCal/validators/input_validation_base.py diff --git a/src/server/BreCal/validators/input_validation_base.py b/src/server/BreCal/validators/input_validation_base.py new file mode 100644 index 0000000..7e51868 --- /dev/null +++ b/src/server/BreCal/validators/input_validation_base.py @@ -0,0 +1,31 @@ +import typing +from marshmallow import ValidationError + +class InputValidationBase: + """ + Base class for input validators. Common validation methods are grouped here. + """ + + @staticmethod + def check_required_fields(content:dict, required_fields:list[str]): + missing_fields = [field for field in required_fields if content.get(field) is None] + if missing_fields: + raise ValidationError({"required_fields": f"Missing required fields: {missing_fields}"}) + + @staticmethod + def check_if_entry_is_already_deleted(entry:dict): + """ + Checks if the entry has 'deleted' set to True/1. + """ + if entry.get("deleted") in [True, 1, "1"]: + raise ValidationError({"deleted": "The selected entry is already deleted."}) + + @staticmethod + def check_deleted_flag_on_post(content:dict): + """ + Checks if 'deleted' is set to 1/True in a POST (Create) request. + """ + if content.get("deleted") in [True, 1, "1"]: + raise ValidationError({"deleted": "Cannot create an entry with 'deleted' set to 1."}) + + diff --git a/src/server/BreCal/validators/input_validation_ship.py b/src/server/BreCal/validators/input_validation_ship.py index 79c547a..5f75a52 100644 --- a/src/server/BreCal/validators/input_validation_ship.py +++ b/src/server/BreCal/validators/input_validation_ship.py @@ -18,10 +18,11 @@ from BreCal.validators.input_validation_utils import check_if_user_is_bsmd_type, from BreCal.database.sql_handler import execute_sql_query_standalone from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag from BreCal.validators.validation_base_utils import check_if_string_has_special_characters +from BreCal.validators.input_validation_base import InputValidationBase import werkzeug -class InputValidationShip(): +class InputValidationShip(InputValidationBase): """ This class combines a complex set of individual input validation functions into a joint object. It uses static methods, so the object does not need to be instantiated, but functions can be called immediately. @@ -55,6 +56,13 @@ class InputValidationShip(): # 3.) Check for reasonable Values (see BreCal.schemas.model.ShipSchema) InputValidationShip.optionally_evaluate_bollard_pull_value(content) + + # 4.) No deleted flag may be set on POST + InputValidationShip.check_deleted_flag_on_post(content) + + # 5.) Check if is_tug is null + InputValidationShip.check_is_tug_null(content) + return @staticmethod @@ -70,6 +78,10 @@ class InputValidationShip(): # 4.) Check for reasonable Values (see BreCal.schemas.model.ShipSchema) InputValidationShip.optionally_evaluate_bollard_pull_value(content) + + # 5.) Check if tug is null + InputValidationShip.check_is_tug_null(content) + return @staticmethod @@ -159,5 +171,11 @@ class InputValidationShip(): raise ValidationError({"deleted":f"The selected ship entry is already deleted."}) return + @staticmethod + def check_is_tug_null(content:dict): + is_tug = content.get("is_tug", None) + if is_tug is None: + raise ValidationError({"is_tug":f"The 'is_tug' property must be set to either True or False."}) + return diff --git a/src/server/BreCal/validators/input_validation_shipcall.py b/src/server/BreCal/validators/input_validation_shipcall.py index 47f8c69..a57ce05 100644 --- a/src/server/BreCal/validators/input_validation_shipcall.py +++ b/src/server/BreCal/validators/input_validation_shipcall.py @@ -17,12 +17,13 @@ from BreCal.database.sql_handler import get_assigned_participant_of_type from BreCal.database.sql_handler import execute_sql_query_standalone from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag from BreCal.validators.validation_base_utils import check_if_string_has_special_characters +from BreCal.validators.input_validation_base import InputValidationBase from BreCal.database.sql_queries import SQLQuery import werkzeug -class InputValidationShipcall(): +class InputValidationShipcall(InputValidationBase): """ This class combines a complex set of individual input validation functions into a joint object. It uses static methods, so the object does not need to be instantiated, but functions can be called immediately. @@ -60,7 +61,11 @@ class InputValidationShipcall(): InputValidationShipcall.check_participant_list_not_empty_when_user_is_agency(loadedModel) # check for reasonable values in the shipcall fields - InputValidationShipcall.check_shipcall_values(loadedModel, content, forbidden_keys=["evaluation", "evaluation_message"]) # "canceled" + InputValidationShipcall.check_shipcall_values(loadedModel, content, forbidden_keys=["evaluation", "evaluation_message", "canceled"]) # "canceled" + + # check for deleted flag on POST + InputValidationShipcall.check_deleted_flag_on_post(content) + return @staticmethod diff --git a/src/server/BreCal/validators/input_validation_times.py b/src/server/BreCal/validators/input_validation_times.py index 780bdce..6e3dd51 100644 --- a/src/server/BreCal/validators/input_validation_times.py +++ b/src/server/BreCal/validators/input_validation_times.py @@ -17,6 +17,7 @@ from BreCal.database.sql_queries import SQLQuery from BreCal.database.sql_handler import execute_sql_query_standalone from BreCal.database.sql_handler import get_assigned_participant_of_type from BreCal.database.sql_utils import get_times_data_for_id +from BreCal.validators.input_validation_base import InputValidationBase from BreCal.validators.validation_base_utils import check_if_int_is_valid_flag, check_if_string_has_special_characters import werkzeug @@ -63,7 +64,7 @@ def build_post_data_type_dependent_required_fields_dict()->dict[ShipcallType,dic -class InputValidationTimes(): +class InputValidationTimes(InputValidationBase): """ This class combines a complex set of individual input validation functions into a joint object. It uses static methods, so the object does not need to be instantiated, but functions can be called immediately. @@ -92,6 +93,10 @@ class InputValidationTimes(): # 4.) Value checking InputValidationTimes.check_dataset_values(user_data, loadedModel, content) + + # 5.) Deleted flag may not be set on POST + InputValidationTimes.check_deleted_flag_on_post(content) + return @staticmethod