diff --git a/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilder.java b/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilder.java index 15866ca..1597897 100644 --- a/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilder.java +++ b/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilder.java @@ -30,15 +30,26 @@ public class ProjectCreationCommandBuilder { private final ProjectExistenceService projectExistenceService; - public ProjectCreationCommand build(CreateProjectRequest request, ClientAppEntity clientApp) { + public ProjectCreationCommand buildForCreation(CreateProjectRequest request, ClientAppEntity clientApp) { ClientAppProjectFlavorEntity flavor = resolveFlavor(request, clientApp); + String projectKey = resolveProjectKey(request.getProjectKey(), flavor); + + return build(request, flavor, projectKey, clientApp); + } + + public ProjectCreationCommand buildForRegistration(CreateProjectRequest request, ClientAppEntity clientApp) { + ClientAppProjectFlavorEntity flavor = resolveFlavor(request, clientApp); + String projectKey = resolveProjectKeyForRegistration(request.getProjectKey(), flavor); + + return build(request, flavor, projectKey, clientApp); + } + private ProjectCreationCommand build(CreateProjectRequest request, ClientAppProjectFlavorEntity flavor, String projectKey, ClientAppEntity clientApp) { String projectFlavor = firstNonBlank(request.getProjectFlavor(), flavor.getName()); String configurationItem = firstNonBlank(request.getConfigurationItem(), flavor.getConfigItem()); String owner = firstNonBlank(request.getOwner(), flavor.getProjectOwner()); String x2account = firstNonBlank(request.getX2OdsAccount(), flavor.getServiceAccount()); String location = firstNonBlank(request.getLocation(), flavor.getLocation()); - String projectKey = resolveProjectKey(request.getProjectKey(), flavor); String projectName = resolveProjectName(request.getProjectName(), projectKey); String projectDescription = firstNonBlank(request.getProjectDescription(), "project " + projectFlavor); @@ -131,6 +142,26 @@ private String resolveProjectKey(String existingProjectKey, ClientAppProjectFlav } } + private String resolveProjectKeyForRegistration(String existingProjectKey, ClientAppProjectFlavorEntity flavor) { + try { + if (Strings.isNotEmpty(existingProjectKey)) { + if (!projectExistenceService.isProjectFoundInCollection(existingProjectKey)) { + return existingProjectKey; + } + + throw new ProjectAlreadyExistsException(ErrorKey.PROJECT_ALREADY_EXISTS); + } + + String pattern = flavor.getProjectKeyPattern(); + + return generateProjectKeyService.generateProjectKey(pattern); + } catch (ProjectKeyGenerationException e) { + throw new ProjectCreationException("Error generating the project key", e); + } catch (ProjectExistenceServiceException e) { + throw new ProjectCreationException("Error checking if the generated key exists: " + e.getMessage(), e); + } + } + private boolean isAllowedConfigItem(String configurationItem, ClientAppProjectFlavorEntity flavor) { String[] allowedConfigItems = flavor.getAllowedConfigItems(); diff --git a/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImpl.java b/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImpl.java index 746fcd4..e8df5f6 100644 --- a/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImpl.java +++ b/api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImpl.java @@ -65,13 +65,14 @@ public CreateProjectResponse createProject(CreateProjectRequest request, UUID cl ClientAppEntity clientApp = clientAppService.findByClientId(clientId); - ProjectCreationCommand command = projectCreationCommandBuilder.build(request, clientApp); - + ProjectCreationCommand command; ProjectResponse project; if (Boolean.TRUE.equals(request.getRegistrationOnly())) { + command = projectCreationCommandBuilder.buildForRegistration(request, clientApp); project = registerProject(command); } else { + command = projectCreationCommandBuilder.buildForCreation(request, clientApp); project = createNewProject(command); } diff --git a/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilderTest.java b/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilderTest.java index 0c71c77..cef7943 100644 --- a/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilderTest.java +++ b/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilderTest.java @@ -50,7 +50,7 @@ void tear_down() throws Exception { } @Test - void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException { + void build_for_creation_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, "KEY01"); @@ -59,7 +59,7 @@ void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throw when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false); - ProjectCreationCommand result = sut.build(request, clientApp); + ProjectCreationCommand result = sut.buildForCreation(request, clientApp); assertEquals("DLSS", result.getProjectFlavor()); assertEquals("CI-001", result.getConfigurationItem()); @@ -69,21 +69,21 @@ void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throw } @Test - void build_resolves_flavor_from_configuration_item_when_flavor_is_not_provided() throws ProjectExistenceServiceException { + void build_for_creation_resolves_flavor_from_configuration_item_when_flavor_is_not_provided() throws ProjectExistenceServiceException { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request(null, "CI-001", "KEY01"); when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false); - ProjectCreationCommand result = sut.build(request, clientApp); + ProjectCreationCommand result = sut.buildForCreation(request, clientApp); assertEquals("DLSS", result.getProjectFlavor()); assertEquals("CI-001", result.getConfigurationItem()); } @Test - void build_generates_project_key_when_request_project_key_is_null() throws ProjectExistenceServiceException, org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException { + void build_for_creation_generates_project_key_when_request_project_key_is_null() throws ProjectExistenceServiceException, org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, null); @@ -91,14 +91,14 @@ void build_generates_project_key_when_request_project_key_is_null() throws Proje when(generateProjectKeyService.generateProjectKey("DLSS%06d")).thenReturn("DLSS000001"); when(projectExistenceService.isProjectFound("DLSS000001")).thenReturn(false); - ProjectCreationCommand result = sut.build(request, clientApp); + ProjectCreationCommand result = sut.buildForCreation(request, clientApp); assertEquals("DLSS000001", result.getProjectKey()); verify(generateProjectKeyService).generateProjectKey("DLSS%06d"); } @Test - void build_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException { + void build_for_creation_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, "KEY01"); @@ -106,35 +106,35 @@ void build_throws_project_already_exists_exception_when_project_key_already_exis when(projectExistenceService.isProjectFound("KEY01")).thenReturn(true); ProjectAlreadyExistsException ex = assertThrows(ProjectAlreadyExistsException.class, - () -> sut.build(request, clientApp)); + () -> sut.buildForCreation(request, clientApp)); assertEquals(ErrorKey.PROJECT_ALREADY_EXISTS, ex.getErrorKey()); } @Test - void build_throws_validation_exception_when_flavor_and_config_item_are_missing() { + void build_for_creation_throws_validation_exception_when_flavor_and_config_item_are_missing() { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request(null, null, "KEY01"); ProjectValidationException ex = assertThrows(ProjectValidationException.class, - () -> sut.build(request, clientApp)); + () -> sut.buildForCreation(request, clientApp)); assertEquals(ErrorKey.BAD_REQUEST_FLAVOR_CONFIG_ITEM, ex.getErrorKey()); } @Test - void build_throws_validation_exception_when_configuration_item_matches_multiple_flavors() { + void build_for_creation_throws_validation_exception_when_configuration_item_matches_multiple_flavors() { ClientAppEntity clientApp = build_client_app(List.of( build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"), build_flavor("AMP", "CI-001", new String[] {}, "eu", "owner2"))); CreateProjectRequest request = build_request(null, "CI-001", "KEY01"); ProjectValidationException ex = assertThrows(ProjectValidationException.class, - () -> sut.build(request, clientApp)); + () -> sut.buildForCreation(request, clientApp)); assertEquals(ErrorKey.INVALID_CONFIG_ITEM, ex.getErrorKey()); } @Test - void build_throws_project_key_generation_exception_when_generation_fails() throws Exception { + void build_for_creation_throws_project_key_generation_exception_when_generation_fails() throws Exception { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, null); @@ -142,11 +142,11 @@ void build_throws_project_key_generation_exception_when_generation_fails() throw when(generateProjectKeyService.generateProjectKey("DLSS%06d")) .thenThrow(new org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException("fail")); - assertThrows(ProjectCreationException.class, () -> sut.build(request, clientApp)); + assertThrows(ProjectCreationException.class, () -> sut.buildForCreation(request, clientApp)); } @Test - void build_throws_project_already_exists_exception_when_project_name_already_exists() throws Exception { + void build_for_creation_throws_project_already_exists_exception_when_project_name_already_exists() throws Exception { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, "KEY01"); @@ -155,11 +155,11 @@ void build_throws_project_already_exists_exception_when_project_name_already_exi when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false); when(projectExistenceService.isProjectFoundByName("Existing Project")).thenReturn(true); - assertThrows(ProjectAlreadyExistsException.class, () -> sut.build(request, clientApp)); + assertThrows(ProjectAlreadyExistsException.class, () -> sut.buildForCreation(request, clientApp)); } @Test - void build_throws_project_creation_exception_when_project_name_check_fails() throws Exception { + void build_for_creation_throws_project_creation_exception_when_project_name_check_fails() throws Exception { ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); ClientAppEntity clientApp = build_client_app(List.of(flavor)); CreateProjectRequest request = build_request("DLSS", null, "KEY01"); @@ -169,7 +169,39 @@ void build_throws_project_creation_exception_when_project_name_check_fails() thr when(projectExistenceService.isProjectFoundByName("Any Project")) .thenThrow(new ProjectExistenceServiceException("lookup failed")); - assertThrows(ProjectCreationException.class, () -> sut.build(request, clientApp)); + assertThrows(ProjectCreationException.class, () -> sut.buildForCreation(request, clientApp)); + } + + @Test + void build_for_registration_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException { + ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); + ClientAppEntity clientApp = build_client_app(List.of(flavor)); + CreateProjectRequest request = build_request("DLSS", null, "KEY01"); + request.setOwner(null); + request.setLocation(null); + + when(projectExistenceService.isProjectFoundInCollection("KEY01")).thenReturn(false); + + ProjectCreationCommand result = sut.buildForRegistration(request, clientApp); + + assertEquals("DLSS", result.getProjectFlavor()); + assertEquals("CI-001", result.getConfigurationItem()); + assertEquals("owner1", result.getOwner()); + assertEquals("eu", result.getLocation()); + assertEquals("KEY01", result.getProjectKey()); + } + + @Test + void build_for_registration_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException { + ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"); + ClientAppEntity clientApp = build_client_app(List.of(flavor)); + CreateProjectRequest request = build_request("DLSS", null, "KEY01"); + + when(projectExistenceService.isProjectFoundInCollection("KEY01")).thenReturn(true); + + ProjectAlreadyExistsException ex = assertThrows(ProjectAlreadyExistsException.class, + () -> sut.buildForRegistration(request, clientApp)); + assertEquals(ErrorKey.PROJECT_ALREADY_EXISTS, ex.getErrorKey()); } private CreateProjectRequest build_request(String flavor, String configItem, String projectKey) { diff --git a/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImplTest.java b/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImplTest.java index dd622ef..a81646c 100644 --- a/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImplTest.java +++ b/api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImplTest.java @@ -101,7 +101,7 @@ void create_project_returns_success_response_when_automation_is_successful() { apiResponse.setProjectFlavor("DLSS"); when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp); - when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command); + when(projectCreationCommandBuilder.buildForCreation(request, clientApp)).thenReturn(command); when(projectMapper.toServiceRequest(command)).thenReturn(serviceRequest); when(projectService.saveProject(serviceRequest)).thenReturn(projectResponse); when(automationParametersMapper.toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111")) @@ -114,7 +114,7 @@ void create_project_returns_success_response_when_automation_is_successful() { assertEquals("Pending", result.getStatus()); assertEquals("DLSS", result.getProjectFlavor()); - verify(projectCreationCommandBuilder).build(request, clientApp); + verify(projectCreationCommandBuilder).buildForCreation(request, clientApp); verify(projectMapper).toServiceRequest(command); verify(automationParametersMapper) .toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111"); @@ -139,7 +139,7 @@ void create_project_with_registrationOnly_returns_success_response_when_automati apiResponse.setProjectFlavor("REGULAR"); when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp); - when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command); + when(projectCreationCommandBuilder.buildForRegistration(request, clientApp)).thenReturn(command); when(projectMapper.toServiceRequest(command)).thenReturn(serviceRequest); when(projectService.saveProject(serviceRequest)).thenReturn(projectResponse); when(projectCreationResponseMapper.toSuccessResponse(command, projectResponse)).thenReturn(apiResponse); @@ -148,7 +148,7 @@ void create_project_with_registrationOnly_returns_success_response_when_automati assertEquals("Running", result.getStatus()); assertEquals("REGULAR", result.getProjectFlavor()); - verify(projectCreationCommandBuilder).build(request, clientApp); + verify(projectCreationCommandBuilder).buildForRegistration(request, clientApp); verify(projectMapper).toServiceRequest(command); verify(automationParametersMapper, never()) .toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111"); @@ -164,7 +164,7 @@ void create_project_throws_project_creation_exception_when_automation_is_not_suc "DLSS01", "name", "desc", "DLSS", "CI-001", "eu", "x2test", "owner", CLIENT_ID); when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp); - when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command); + when(projectCreationCommandBuilder.buildForCreation(request, clientApp)).thenReturn(command); when(projectMapper.toServiceRequest(command)).thenReturn(new ProjectRequest()); when(projectService.saveProject(any(ProjectRequest.class))) .thenReturn(ProjectResponse.builder() diff --git a/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/ProjectExistenceService.java b/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/ProjectExistenceService.java index 3933043..7ab8dd5 100644 --- a/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/ProjectExistenceService.java +++ b/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/ProjectExistenceService.java @@ -7,4 +7,6 @@ public interface ProjectExistenceService { boolean isProjectFound(String projectKey) throws ProjectExistenceServiceException; boolean isProjectFoundByName(String projecName) throws ProjectExistenceServiceException; + + boolean isProjectFoundInCollection(String projectKey) throws ProjectExistenceServiceException; } diff --git a/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/impl/ProjectExistenceServiceImpl.java b/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/impl/ProjectExistenceServiceImpl.java index c576256..76e02e0 100644 --- a/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/impl/ProjectExistenceServiceImpl.java +++ b/service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/impl/ProjectExistenceServiceImpl.java @@ -58,6 +58,11 @@ public boolean isProjectFoundByName(String projecName) throws ProjectExistenceSe return !projectService.findProjectsByName(projecName).isEmpty(); } + @Override + public boolean isProjectFoundInCollection(String projectKey) throws ProjectExistenceServiceException { + return existsInCollection(projectKey); + } + private boolean existsInCollection(String projectKey) { return projectService.getProject(projectKey) != null; }