Skip to content

Commit e875897

Browse files
authored
Fix/project registration checks if already exists (#26)
There was a bug when registering a project that it was returning ProjectAlreadyExistsException because it was not omitting checks in Jira, Bitbucket and Openshift. Code has been updated to only check in Collection when this flag is raised. It checks everything otherwise.
1 parent b95a7f3 commit e875897

6 files changed

Lines changed: 98 additions & 27 deletions

File tree

api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilder.java

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,15 +30,26 @@ public class ProjectCreationCommandBuilder {
3030

3131
private final ProjectExistenceService projectExistenceService;
3232

33-
public ProjectCreationCommand build(CreateProjectRequest request, ClientAppEntity clientApp) {
33+
public ProjectCreationCommand buildForCreation(CreateProjectRequest request, ClientAppEntity clientApp) {
3434
ClientAppProjectFlavorEntity flavor = resolveFlavor(request, clientApp);
35+
String projectKey = resolveProjectKey(request.getProjectKey(), flavor);
36+
37+
return build(request, flavor, projectKey, clientApp);
38+
}
39+
40+
public ProjectCreationCommand buildForRegistration(CreateProjectRequest request, ClientAppEntity clientApp) {
41+
ClientAppProjectFlavorEntity flavor = resolveFlavor(request, clientApp);
42+
String projectKey = resolveProjectKeyForRegistration(request.getProjectKey(), flavor);
43+
44+
return build(request, flavor, projectKey, clientApp);
45+
}
3546

47+
private ProjectCreationCommand build(CreateProjectRequest request, ClientAppProjectFlavorEntity flavor, String projectKey, ClientAppEntity clientApp) {
3648
String projectFlavor = firstNonBlank(request.getProjectFlavor(), flavor.getName());
3749
String configurationItem = firstNonBlank(request.getConfigurationItem(), flavor.getConfigItem());
3850
String owner = firstNonBlank(request.getOwner(), flavor.getProjectOwner());
3951
String x2account = firstNonBlank(request.getX2OdsAccount(), flavor.getServiceAccount());
4052
String location = firstNonBlank(request.getLocation(), flavor.getLocation());
41-
String projectKey = resolveProjectKey(request.getProjectKey(), flavor);
4253
String projectName = resolveProjectName(request.getProjectName(), projectKey);
4354
String projectDescription = firstNonBlank(request.getProjectDescription(), "project " + projectFlavor);
4455

@@ -131,6 +142,26 @@ private String resolveProjectKey(String existingProjectKey, ClientAppProjectFlav
131142
}
132143
}
133144

145+
private String resolveProjectKeyForRegistration(String existingProjectKey, ClientAppProjectFlavorEntity flavor) {
146+
try {
147+
if (Strings.isNotEmpty(existingProjectKey)) {
148+
if (!projectExistenceService.isProjectFoundInCollection(existingProjectKey)) {
149+
return existingProjectKey;
150+
}
151+
152+
throw new ProjectAlreadyExistsException(ErrorKey.PROJECT_ALREADY_EXISTS);
153+
}
154+
155+
String pattern = flavor.getProjectKeyPattern();
156+
157+
return generateProjectKeyService.generateProjectKey(pattern);
158+
} catch (ProjectKeyGenerationException e) {
159+
throw new ProjectCreationException("Error generating the project key", e);
160+
} catch (ProjectExistenceServiceException e) {
161+
throw new ProjectCreationException("Error checking if the generated key exists: " + e.getMessage(), e);
162+
}
163+
}
164+
134165
private boolean isAllowedConfigItem(String configurationItem, ClientAppProjectFlavorEntity flavor) {
135166
String[] allowedConfigItems = flavor.getAllowedConfigItems();
136167

api-project/src/main/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImpl.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,13 +65,14 @@ public CreateProjectResponse createProject(CreateProjectRequest request, UUID cl
6565

6666
ClientAppEntity clientApp = clientAppService.findByClientId(clientId);
6767

68-
ProjectCreationCommand command = projectCreationCommandBuilder.build(request, clientApp);
69-
68+
ProjectCreationCommand command;
7069
ProjectResponse project;
7170

7271
if (Boolean.TRUE.equals(request.getRegistrationOnly())) {
72+
command = projectCreationCommandBuilder.buildForRegistration(request, clientApp);
7373
project = registerProject(command);
7474
} else {
75+
command = projectCreationCommandBuilder.buildForCreation(request, clientApp);
7576
project = createNewProject(command);
7677
}
7778

api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectCreationCommandBuilderTest.java

Lines changed: 50 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void tear_down() throws Exception {
5050
}
5151

5252
@Test
53-
void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException {
53+
void build_for_creation_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException {
5454
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
5555
ClientAppEntity clientApp = build_client_app(List.of(flavor));
5656
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
@@ -59,7 +59,7 @@ void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throw
5959

6060
when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false);
6161

62-
ProjectCreationCommand result = sut.build(request, clientApp);
62+
ProjectCreationCommand result = sut.buildForCreation(request, clientApp);
6363

6464
assertEquals("DLSS", result.getProjectFlavor());
6565
assertEquals("CI-001", result.getConfigurationItem());
@@ -69,84 +69,84 @@ void build_resolves_defaults_from_flavor_when_request_fields_are_missing() throw
6969
}
7070

7171
@Test
72-
void build_resolves_flavor_from_configuration_item_when_flavor_is_not_provided() throws ProjectExistenceServiceException {
72+
void build_for_creation_resolves_flavor_from_configuration_item_when_flavor_is_not_provided() throws ProjectExistenceServiceException {
7373
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
7474
ClientAppEntity clientApp = build_client_app(List.of(flavor));
7575
CreateProjectRequest request = build_request(null, "CI-001", "KEY01");
7676

7777
when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false);
7878

79-
ProjectCreationCommand result = sut.build(request, clientApp);
79+
ProjectCreationCommand result = sut.buildForCreation(request, clientApp);
8080

8181
assertEquals("DLSS", result.getProjectFlavor());
8282
assertEquals("CI-001", result.getConfigurationItem());
8383
}
8484

8585
@Test
86-
void build_generates_project_key_when_request_project_key_is_null() throws ProjectExistenceServiceException, org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException {
86+
void build_for_creation_generates_project_key_when_request_project_key_is_null() throws ProjectExistenceServiceException, org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException {
8787
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
8888
ClientAppEntity clientApp = build_client_app(List.of(flavor));
8989
CreateProjectRequest request = build_request("DLSS", null, null);
9090

9191
when(generateProjectKeyService.generateProjectKey("DLSS%06d")).thenReturn("DLSS000001");
9292
when(projectExistenceService.isProjectFound("DLSS000001")).thenReturn(false);
9393

94-
ProjectCreationCommand result = sut.build(request, clientApp);
94+
ProjectCreationCommand result = sut.buildForCreation(request, clientApp);
9595

9696
assertEquals("DLSS000001", result.getProjectKey());
9797
verify(generateProjectKeyService).generateProjectKey("DLSS%06d");
9898
}
9999

100100
@Test
101-
void build_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException {
101+
void build_for_creation_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException {
102102
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
103103
ClientAppEntity clientApp = build_client_app(List.of(flavor));
104104
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
105105

106106
when(projectExistenceService.isProjectFound("KEY01")).thenReturn(true);
107107

108108
ProjectAlreadyExistsException ex = assertThrows(ProjectAlreadyExistsException.class,
109-
() -> sut.build(request, clientApp));
109+
() -> sut.buildForCreation(request, clientApp));
110110
assertEquals(ErrorKey.PROJECT_ALREADY_EXISTS, ex.getErrorKey());
111111
}
112112

113113
@Test
114-
void build_throws_validation_exception_when_flavor_and_config_item_are_missing() {
114+
void build_for_creation_throws_validation_exception_when_flavor_and_config_item_are_missing() {
115115
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
116116
ClientAppEntity clientApp = build_client_app(List.of(flavor));
117117
CreateProjectRequest request = build_request(null, null, "KEY01");
118118

119119
ProjectValidationException ex = assertThrows(ProjectValidationException.class,
120-
() -> sut.build(request, clientApp));
120+
() -> sut.buildForCreation(request, clientApp));
121121
assertEquals(ErrorKey.BAD_REQUEST_FLAVOR_CONFIG_ITEM, ex.getErrorKey());
122122
}
123123

124124
@Test
125-
void build_throws_validation_exception_when_configuration_item_matches_multiple_flavors() {
125+
void build_for_creation_throws_validation_exception_when_configuration_item_matches_multiple_flavors() {
126126
ClientAppEntity clientApp = build_client_app(List.of(
127127
build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1"),
128128
build_flavor("AMP", "CI-001", new String[] {}, "eu", "owner2")));
129129
CreateProjectRequest request = build_request(null, "CI-001", "KEY01");
130130

131131
ProjectValidationException ex = assertThrows(ProjectValidationException.class,
132-
() -> sut.build(request, clientApp));
132+
() -> sut.buildForCreation(request, clientApp));
133133
assertEquals(ErrorKey.INVALID_CONFIG_ITEM, ex.getErrorKey());
134134
}
135135

136136
@Test
137-
void build_throws_project_key_generation_exception_when_generation_fails() throws Exception {
137+
void build_for_creation_throws_project_key_generation_exception_when_generation_fails() throws Exception {
138138
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
139139
ClientAppEntity clientApp = build_client_app(List.of(flavor));
140140
CreateProjectRequest request = build_request("DLSS", null, null);
141141

142142
when(generateProjectKeyService.generateProjectKey("DLSS%06d"))
143143
.thenThrow(new org.opendevstack.apiservice.serviceproject.exception.ProjectKeyGenerationException("fail"));
144144

145-
assertThrows(ProjectCreationException.class, () -> sut.build(request, clientApp));
145+
assertThrows(ProjectCreationException.class, () -> sut.buildForCreation(request, clientApp));
146146
}
147147

148148
@Test
149-
void build_throws_project_already_exists_exception_when_project_name_already_exists() throws Exception {
149+
void build_for_creation_throws_project_already_exists_exception_when_project_name_already_exists() throws Exception {
150150
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
151151
ClientAppEntity clientApp = build_client_app(List.of(flavor));
152152
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
@@ -155,11 +155,11 @@ void build_throws_project_already_exists_exception_when_project_name_already_exi
155155
when(projectExistenceService.isProjectFound("KEY01")).thenReturn(false);
156156
when(projectExistenceService.isProjectFoundByName("Existing Project")).thenReturn(true);
157157

158-
assertThrows(ProjectAlreadyExistsException.class, () -> sut.build(request, clientApp));
158+
assertThrows(ProjectAlreadyExistsException.class, () -> sut.buildForCreation(request, clientApp));
159159
}
160160

161161
@Test
162-
void build_throws_project_creation_exception_when_project_name_check_fails() throws Exception {
162+
void build_for_creation_throws_project_creation_exception_when_project_name_check_fails() throws Exception {
163163
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
164164
ClientAppEntity clientApp = build_client_app(List.of(flavor));
165165
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
@@ -169,7 +169,39 @@ void build_throws_project_creation_exception_when_project_name_check_fails() thr
169169
when(projectExistenceService.isProjectFoundByName("Any Project"))
170170
.thenThrow(new ProjectExistenceServiceException("lookup failed"));
171171

172-
assertThrows(ProjectCreationException.class, () -> sut.build(request, clientApp));
172+
assertThrows(ProjectCreationException.class, () -> sut.buildForCreation(request, clientApp));
173+
}
174+
175+
@Test
176+
void build_for_registration_resolves_defaults_from_flavor_when_request_fields_are_missing() throws ProjectExistenceServiceException {
177+
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
178+
ClientAppEntity clientApp = build_client_app(List.of(flavor));
179+
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
180+
request.setOwner(null);
181+
request.setLocation(null);
182+
183+
when(projectExistenceService.isProjectFoundInCollection("KEY01")).thenReturn(false);
184+
185+
ProjectCreationCommand result = sut.buildForRegistration(request, clientApp);
186+
187+
assertEquals("DLSS", result.getProjectFlavor());
188+
assertEquals("CI-001", result.getConfigurationItem());
189+
assertEquals("owner1", result.getOwner());
190+
assertEquals("eu", result.getLocation());
191+
assertEquals("KEY01", result.getProjectKey());
192+
}
193+
194+
@Test
195+
void build_for_registration_throws_project_already_exists_exception_when_project_key_already_exists() throws ProjectExistenceServiceException {
196+
ClientAppProjectFlavorEntity flavor = build_flavor("DLSS", "CI-001", new String[] {}, "eu", "owner1");
197+
ClientAppEntity clientApp = build_client_app(List.of(flavor));
198+
CreateProjectRequest request = build_request("DLSS", null, "KEY01");
199+
200+
when(projectExistenceService.isProjectFoundInCollection("KEY01")).thenReturn(true);
201+
202+
ProjectAlreadyExistsException ex = assertThrows(ProjectAlreadyExistsException.class,
203+
() -> sut.buildForRegistration(request, clientApp));
204+
assertEquals(ErrorKey.PROJECT_ALREADY_EXISTS, ex.getErrorKey());
173205
}
174206

175207
private CreateProjectRequest build_request(String flavor, String configItem, String projectKey) {

api-project/src/test/java/org/opendevstack/apiservice/project/facade/impl/ProjectsFacadeImplTest.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void create_project_returns_success_response_when_automation_is_successful() {
101101
apiResponse.setProjectFlavor("DLSS");
102102

103103
when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp);
104-
when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command);
104+
when(projectCreationCommandBuilder.buildForCreation(request, clientApp)).thenReturn(command);
105105
when(projectMapper.toServiceRequest(command)).thenReturn(serviceRequest);
106106
when(projectService.saveProject(serviceRequest)).thenReturn(projectResponse);
107107
when(automationParametersMapper.toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111"))
@@ -114,7 +114,7 @@ void create_project_returns_success_response_when_automation_is_successful() {
114114

115115
assertEquals("Pending", result.getStatus());
116116
assertEquals("DLSS", result.getProjectFlavor());
117-
verify(projectCreationCommandBuilder).build(request, clientApp);
117+
verify(projectCreationCommandBuilder).buildForCreation(request, clientApp);
118118
verify(projectMapper).toServiceRequest(command);
119119
verify(automationParametersMapper)
120120
.toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111");
@@ -139,7 +139,7 @@ void create_project_with_registrationOnly_returns_success_response_when_automati
139139
apiResponse.setProjectFlavor("REGULAR");
140140

141141
when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp);
142-
when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command);
142+
when(projectCreationCommandBuilder.buildForRegistration(request, clientApp)).thenReturn(command);
143143
when(projectMapper.toServiceRequest(command)).thenReturn(serviceRequest);
144144
when(projectService.saveProject(serviceRequest)).thenReturn(projectResponse);
145145
when(projectCreationResponseMapper.toSuccessResponse(command, projectResponse)).thenReturn(apiResponse);
@@ -148,7 +148,7 @@ void create_project_with_registrationOnly_returns_success_response_when_automati
148148

149149
assertEquals("Running", result.getStatus());
150150
assertEquals("REGULAR", result.getProjectFlavor());
151-
verify(projectCreationCommandBuilder).build(request, clientApp);
151+
verify(projectCreationCommandBuilder).buildForRegistration(request, clientApp);
152152
verify(projectMapper).toServiceRequest(command);
153153
verify(automationParametersMapper, never())
154154
.toWorkflowParameters(command, "11111111-1111-1111-1111-111111111111");
@@ -164,7 +164,7 @@ void create_project_throws_project_creation_exception_when_automation_is_not_suc
164164
"DLSS01", "name", "desc", "DLSS", "CI-001", "eu", "x2test", "owner", CLIENT_ID);
165165

166166
when(clientAppService.findByClientId(CLIENT_ID)).thenReturn(clientApp);
167-
when(projectCreationCommandBuilder.build(request, clientApp)).thenReturn(command);
167+
when(projectCreationCommandBuilder.buildForCreation(request, clientApp)).thenReturn(command);
168168
when(projectMapper.toServiceRequest(command)).thenReturn(new ProjectRequest());
169169
when(projectService.saveProject(any(ProjectRequest.class)))
170170
.thenReturn(ProjectResponse.builder()

service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/ProjectExistenceService.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@ public interface ProjectExistenceService {
77
boolean isProjectFound(String projectKey) throws ProjectExistenceServiceException;
88

99
boolean isProjectFoundByName(String projecName) throws ProjectExistenceServiceException;
10+
11+
boolean isProjectFoundInCollection(String projectKey) throws ProjectExistenceServiceException;
1012
}

service-projects/src/main/java/org/opendevstack/apiservice/serviceproject/service/impl/ProjectExistenceServiceImpl.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public boolean isProjectFoundByName(String projecName) throws ProjectExistenceSe
5858
return !projectService.findProjectsByName(projecName).isEmpty();
5959
}
6060

61+
@Override
62+
public boolean isProjectFoundInCollection(String projectKey) throws ProjectExistenceServiceException {
63+
return existsInCollection(projectKey);
64+
}
65+
6166
private boolean existsInCollection(String projectKey) {
6267
return projectService.getProject(projectKey) != null;
6368
}

0 commit comments

Comments
 (0)