diff --git a/.flake8 b/.flake8 index b42cf528..66efd2c7 100644 --- a/.flake8 +++ b/.flake8 @@ -10,6 +10,11 @@ rst-directives = deprecated per-file-ignores = # More specific globs seem to overwrite the more generic ones so we have # to split them out by directory + # So if you have a rule like: + # tests/*: D102,D103 + # and a rule like: + # tests/test_hey.py: D102 + # THEN, test_hey.py will NOT be excluding D103 # asserts are ok in tests tests/*:S101,D102,D103 @@ -34,4 +39,4 @@ per-file-ignores = # and ignore long comment line src/spiffworkflow_backend/services/logging_service.py:N802,B950 - tests/spiffworkflow_backend/integration/test_process_api.py:S607,S101,D103,S605 + tests/spiffworkflow_backend/integration/test_process_api.py:S607,S101,S605,D102,D103,D101 diff --git a/src/spiffworkflow_backend/routes/process_instances_controller.py b/src/spiffworkflow_backend/routes/process_instances_controller.py index 1271f929..679c2fa7 100644 --- a/src/spiffworkflow_backend/routes/process_instances_controller.py +++ b/src/spiffworkflow_backend/routes/process_instances_controller.py @@ -72,6 +72,18 @@ def process_instance_create( process_model_identifier = _un_modify_modified_process_model_id( modified_process_model_identifier ) + + process_model = _get_process_model(process_model_identifier) + if process_model.primary_file_name is None: + raise ApiError( + error_code="process_model_missing_primary_bpmn_file", + message=( + f"Process Model '{process_model_identifier}' does not have a primary" + " bpmn file. One must be set in order to instantiate this model." + ), + status_code=400, + ) + process_instance = ( ProcessInstanceService.create_process_instance_from_process_model_identifier( process_model_identifier, g.user diff --git a/src/spiffworkflow_backend/routes/process_models_controller.py b/src/spiffworkflow_backend/routes/process_models_controller.py index 694c01ef..19f064c9 100644 --- a/src/spiffworkflow_backend/routes/process_models_controller.py +++ b/src/spiffworkflow_backend/routes/process_models_controller.py @@ -277,6 +277,17 @@ def process_model_file_delete( """Process_model_file_delete.""" process_model_identifier = modified_process_model_identifier.replace(":", "/") process_model = _get_process_model(process_model_identifier) + if process_model.primary_file_name == file_name: + raise ApiError( + error_code="process_model_file_cannot_be_deleted", + message=( + f"'{file_name}' is the primary bpmn file for" + f" '{process_model_identifier}' and cannot be deleted. Please set" + " another file as the primary before attempting to delete this one." + ), + status_code=400, + ) + try: SpecFileService.delete_file(process_model, file_name) except FileNotFoundError as exception: diff --git a/tests/spiffworkflow_backend/integration/test_process_api.py b/tests/spiffworkflow_backend/integration/test_process_api.py index ebc26ac6..7213e31c 100644 --- a/tests/spiffworkflow_backend/integration/test_process_api.py +++ b/tests/spiffworkflow_backend/integration/test_process_api.py @@ -922,6 +922,28 @@ class TestProcessApi(BaseTest): assert response.json is not None assert response.json["error_code"] == "process_model_file_cannot_be_found" + def test_process_model_file_delete_when_primary_file( + self, + app: Flask, + client: FlaskClient, + with_db_and_bpmn_file_cleanup: None, + with_super_admin_user: UserModel, + ) -> None: + process_model_identifier = self.create_group_and_model_with_bpmn( + client, with_super_admin_user + ) + modified_process_model_identifier = process_model_identifier.replace("/", ":") + + response = client.delete( + f"/v1.0/process-models/{modified_process_model_identifier}/files/random_fact.bpmn", + follow_redirects=True, + headers=self.logged_in_headers(with_super_admin_user), + ) + + assert response.status_code == 400 + assert response.json is not None + assert response.json["error_code"] == "process_model_file_cannot_be_deleted" + def test_process_model_file_delete( self, app: Flask, @@ -935,8 +957,16 @@ class TestProcessApi(BaseTest): ) modified_process_model_identifier = process_model_identifier.replace("/", ":") + self.create_spec_file( + client, + process_model_id=process_model_identifier, + file_name="second_file.json", + file_data=b"