@@ -19,6 +19,7 @@ | |||
*/ | |||
package org.sonar.server.project.ws; | |||
import java.util.Set; | |||
import javax.annotation.CheckForNull; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.server.ws.Change; | |||
@@ -99,9 +100,18 @@ public class CreateAction implements ProjectsWsAction { | |||
@Override | |||
public void handle(Request request, Response response) throws Exception { | |||
CreateRequest createRequest = toCreateRequest(request); | |||
validate(createRequest); | |||
writeProtobuf(doHandle(createRequest), request, response); | |||
} | |||
private static void validate(CreateRequest createRequest) { | |||
Set<String> forbiddenNamePhrases = Set.of(":BRANCH:", ":PULLREQUEST:"); | |||
if (forbiddenNamePhrases.stream().anyMatch(createRequest.getProjectKey()::contains)) { | |||
throw new IllegalArgumentException(String.format("Invalid project key. Project key must not contain following phrases [%s]", | |||
String.join(", ", forbiddenNamePhrases))); | |||
} | |||
} | |||
private CreateWsResponse doHandle(CreateRequest request) { | |||
try (DbSession dbSession = dbClient.openSession(false)) { | |||
userSession.checkPermission(PROVISION_PROJECTS); |
@@ -91,6 +91,27 @@ public class CreateActionTest { | |||
when(projectDefaultVisibility.get(any())).thenReturn(Visibility.PUBLIC); | |||
} | |||
@Test | |||
public void fail_if_invalid_project_name() { | |||
userSession.addPermission(PROVISION_PROJECTS); | |||
var createRequestBRANCHinKey = CreateRequest.builder() | |||
.setProjectKey("test:BRANCH:test") | |||
.setName(DEFAULT_PROJECT_NAME) | |||
.build(); | |||
assertThatThrownBy(() -> call(createRequestBRANCHinKey)) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Invalid project key. Project key must not contain following phrases [:PULLREQUEST:, :BRANCH:]"); | |||
var createRequestPRinKey = CreateRequest.builder() | |||
.setProjectKey("test:PULLREQUEST:test") | |||
.setName(DEFAULT_PROJECT_NAME) | |||
.build(); | |||
assertThatThrownBy(() -> call(createRequestPRinKey)) | |||
.isInstanceOf(IllegalArgumentException.class) | |||
.hasMessage("Invalid project key. Project key must not contain following phrases [:PULLREQUEST:, :BRANCH:]"); | |||
} | |||
@Test | |||
public void create_project() { | |||
userSession.addPermission(PROVISION_PROJECTS); |
@@ -20,7 +20,9 @@ | |||
package org.sonar.scanner.scan; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.stream.Stream; | |||
import javax.annotation.Nullable; | |||
import org.sonar.api.batch.bootstrap.ProjectDefinition; | |||
@@ -102,6 +104,11 @@ public class ProjectReactorValidator { | |||
if (!ComponentKeys.isValidProjectKey(projectDefinition.getKey())) { | |||
validationMessages.add(format("\"%s\" is not a valid project key. %s.", projectDefinition.getKey(), ALLOWED_CHARACTERS_MESSAGE)); | |||
} | |||
Set<String> forbiddenNamePhrases = Set.of(":BRANCH:", ":PULLREQUEST:"); | |||
if (forbiddenNamePhrases.stream().anyMatch(projectDefinition.getKey()::contains)) { | |||
validationMessages.add(format("\"%s\" is not a valid project key. Project key must not contain following phrases [%s]", projectDefinition.getKey(), | |||
String.join(", ", forbiddenNamePhrases))); | |||
} | |||
} | |||
private boolean isBranchFeatureAvailable() { |
@@ -87,7 +87,7 @@ public class ProjectReactorValidatorTest { | |||
} | |||
@Test | |||
public void failg_when_invalid_key() { | |||
public void fail_when_invalid_key() { | |||
ProjectReactor reactor = createProjectReactor("foo$bar"); | |||
assertThatThrownBy(() -> underTest.validate(reactor)) | |||
@@ -96,6 +96,23 @@ public class ProjectReactorValidatorTest { | |||
+ " '-', '_', '.' and ':', with at least one non-digit."); | |||
} | |||
@Test | |||
public void fail_when_key_contains_invalid_phrases() { | |||
ProjectReactor reactorWithBranchInKey = createProjectReactor("test:BRANCH:test"); | |||
assertThatThrownBy(() -> underTest.validate(reactorWithBranchInKey)) | |||
.isInstanceOf(MessageException.class) | |||
.hasMessageContainingAll("\"test:BRANCH:test\" is not a valid project key. " | |||
+ "Project key must not contain following phrases", ":BRANCH:", ":PULLREQUEST:"); | |||
ProjectReactor reactorWithPRinKey = createProjectReactor("test:PULLREQUEST:test"); | |||
assertThatThrownBy(() -> underTest.validate(reactorWithPRinKey)) | |||
.isInstanceOf(MessageException.class) | |||
.hasMessageContainingAll("\"test:PULLREQUEST:test\" is not a valid project key. " | |||
+ "Project key must not contain following phrases", ":BRANCH:", ":PULLREQUEST:"); | |||
} | |||
@Test | |||
public void fail_when_only_digits() { | |||
ProjectReactor reactor = createProjectReactor("12345"); |