]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7992 Restrict length of version names
authorDaniel Schwarz <bartfastiel@users.noreply.github.com>
Wed, 25 Oct 2017 16:08:20 +0000 (18:08 +0200)
committerJulien HENRY <julien.henry@sonarsource.com>
Wed, 25 Oct 2017 16:08:20 +0000 (02:08 +1000)
* SONAR-7992 Restrict length of name in api/project_analyses/update_event
to 100 characters
* SONAR-7992 Restrict length of version name of an analysis
* SONAR-7992 Restrict length of version name of SnapshotDto
* SONAR-7992 Include the module's name in the validation error message

server/sonar-db-dao/src/main/java/org/sonar/db/component/SnapshotDto.java
server/sonar-db-dao/src/test/java/org/sonar/db/component/SnapshotDtoTest.java
server/sonar-server/src/main/java/org/sonar/server/projectanalysis/ws/UpdateEventAction.java
server/sonar-server/src/test/java/org/sonar/server/projectanalysis/ws/UpdateEventActionTest.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectReactorValidator.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectReactorValidatorTest.java

index e326b4da5115f9a7a40097f905d64b91ccfb388d..1dfec6f1b93ce0f30730dc412e3c44c1a1b33572 100644 (file)
@@ -22,6 +22,8 @@ package org.sonar.db.component;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nullable;
 
+import static com.google.common.base.Preconditions.checkArgument;
+
 public final class SnapshotDto {
 
   /**
@@ -29,6 +31,7 @@ public final class SnapshotDto {
    */
   public static final String STATUS_UNPROCESSED = "U";
   public static final String STATUS_PROCESSED = "P";
+  public static final int MAX_VERSION_LENGTH = 100;
 
   private Long id;
   private String uuid;
@@ -116,6 +119,10 @@ public final class SnapshotDto {
   }
 
   public SnapshotDto setVersion(@Nullable String version) {
+    if (version != null) {
+      checkArgument(version.length() <= MAX_VERSION_LENGTH,
+        "Event name length (%s) is longer than the maximum authorized (%s). '%s' was provided.", version.length(), MAX_VERSION_LENGTH, version);
+    }
     this.version = version;
     return this;
   }
index 4b8dd3e26afe9caa8bee81c75dd01654713f19bc..5cbed4b6e3d114e0582a456e63332479b2bcb068 100644 (file)
  */
 package org.sonar.db.component;
 
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
 
+import static org.apache.commons.lang.StringUtils.repeat;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.api.utils.DateUtils.parseDate;
 
 public class SnapshotDtoTest {
 
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+
   @Test
   public void test_getter_and_setter() throws Exception {
     SnapshotDto snapshotDto = new SnapshotDto()
@@ -48,4 +54,17 @@ public class SnapshotDtoTest {
     assertThat(snapshotDto.getPeriodDate()).isEqualTo(parseDate("2014-06-01").getTime());
   }
 
+  @Test
+  public void fail_if_version_name_is_longer_then_100_characters() throws Exception {
+    SnapshotDto snapshotDto = new SnapshotDto();
+    snapshotDto.setVersion(null);
+    snapshotDto.setVersion("1.0");
+    snapshotDto.setVersion(repeat("a", 100));
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Event name length (101) is longer than the maximum authorized (100). " +
+      "'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' was provided.");
+
+    snapshotDto.setVersion(repeat("a", 101));
+  }
 }
index 75ac36478dcf77f347dcc1fad6cc5738c451635d..488d39d6d5fb2293fadaabf2a2a65333648496e5 100644 (file)
@@ -52,6 +52,7 @@ import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameter
 import static org.sonarqube.ws.client.projectanalysis.ProjectAnalysesWsParameters.PARAM_NAME;
 
 public class UpdateEventAction implements ProjectAnalysesWsAction {
+  private static final int MAX_NAME_LENGTH = 100;
   private final DbClient dbClient;
   private final UserSession userSession;
 
@@ -100,6 +101,7 @@ public class UpdateEventAction implements ProjectAnalysesWsAction {
         .of(getDbEvent(dbSession, request))
         .peek(checkPermissions())
         .peek(checkModifiable())
+        .peek(checkVersionNameLength(request))
         .map(updateNameAndDescription(request))
         .peek(checkNonConflictingOtherEvents(dbSession))
         .peek(updateInDb(dbSession))
@@ -146,6 +148,16 @@ public class UpdateEventAction implements ProjectAnalysesWsAction {
     };
   }
 
+  private static Consumer<EventDto> checkVersionNameLength(UpdateEventRequest request) {
+    String name = request.getName();
+    return candidateEvent -> {
+      if (name != null && VERSION.getLabel().equals(candidateEvent.getCategory())) {
+        checkArgument(name.length() <= MAX_NAME_LENGTH,
+          "Version length (%s) is longer than the maximum authorized (%s). '%s' was provided.", name.length(), MAX_NAME_LENGTH, name);
+      }
+    };
+  }
+
   private SnapshotDto getAnalysis(DbSession dbSession, EventDto event) {
     return dbClient.snapshotDao().selectByUuid(dbSession, event.getAnalysisUuid())
       .orElseThrow(() -> new IllegalStateException(format("Analysis '%s' is not found", event.getAnalysisUuid())));
index bae882ed3c11ba10a9b19c8039aeb9dd2e424361..48d788a1406fed90ba6345e58bf9d98cf10a4aab 100644 (file)
@@ -41,6 +41,7 @@ import org.sonar.server.ws.WsActionTester;
 import org.sonarqube.ws.ProjectAnalyses;
 import org.sonarqube.ws.ProjectAnalyses.UpdateEventResponse;
 
+import static org.apache.commons.lang.StringUtils.repeat;
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.sonar.core.util.Protobuf.setNullable;
 import static org.sonar.db.component.SnapshotTesting.newAnalysis;
@@ -223,6 +224,22 @@ public class UpdateEventActionTest {
     call("E2", "E1 name");
   }
 
+  @Test
+  public void limit_version_name_length_to_100_for_analysis_events() {
+    SnapshotDto analysis = createAnalysisAndLogInAsProjectAdministrator("5.6");
+    db.events().insertEvent(newEvent(analysis).setUuid("E1").setCategory(OTHER.getLabel()).setName("E1 name"));
+    db.events().insertEvent(newEvent(analysis).setUuid("E2").setCategory(VERSION.getLabel()).setName("E2 name"));
+
+    call("E1", repeat("a", 100));
+    call("E1", repeat("a", 101));
+    call("E2", repeat("a", 100));
+
+    expectedException.expect(IllegalArgumentException.class);
+    expectedException.expectMessage("Version length (101) is longer than the maximum authorized (100). 'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa' was provided");
+
+    call("E2", repeat("a", 101));
+  }
+
   private UpdateEventResponse call(@Nullable String eventUuid, @Nullable String name) {
     TestRequest request = ws.newRequest()
       .setMethod(POST.name());
index e9b5a5bd05441ff47606a4829f5a6c8aac0ca783..f91f4067fd5b57b4e3dda7df6fa4f319c4e8b8e3 100644 (file)
@@ -104,6 +104,11 @@ public class ProjectReactorValidator {
       validationMessages.add(String.format("\"%s\" is not a valid project or module key. "
         + "Allowed characters are alphanumeric, '-', '_', '.' and ':', with at least one non-digit.", moduleDef.getKey()));
     }
+    String originalVersion = moduleDef.getOriginalVersion();
+    if (originalVersion != null && originalVersion.length() > 100) {
+      validationMessages.add(String.format("\"%s\" is not a valid version name for module \"%s\". " +
+        "The maximum length for version numbers is 100 characters.", originalVersion, moduleDef.getKey()));
+    }
   }
 
   private static void validateBranch(List<String> validationMessages, @Nullable String branch) {
index 9a3c0a86158b2101074024ef5c33d26dad09dd49..dbfafbe23f4bf7e178687432928e5b3f52811f29 100644 (file)
@@ -19,6 +19,8 @@
  */
 package org.sonar.scanner.scan;
 
+import java.util.Arrays;
+import java.util.function.Consumer;
 import java.util.Optional;
 import org.junit.Before;
 import org.junit.Rule;
@@ -32,6 +34,7 @@ import org.sonar.api.utils.MessageException;
 import org.sonar.core.config.ScannerProperties;
 import org.sonar.scanner.bootstrap.GlobalConfiguration;
 
+import static org.apache.commons.lang.StringUtils.repeat;
 import static org.mockito.Matchers.anyString;
 import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
@@ -187,17 +190,33 @@ public class ProjectReactorValidatorTest {
     validator.validate(reactor);
   }
 
-  private ProjectReactor createProjectReactor(String projectKey) {
-    ProjectDefinition def = ProjectDefinition.create().setProperty(CoreProperties.PROJECT_KEY_PROPERTY, projectKey);
-    ProjectReactor reactor = new ProjectReactor(def);
-    return reactor;
+  @Test
+  public void not_fail_with_valid_version() {
+    validator.validate(createProjectReactor("foo", def -> def.setVersion("1.0")));
+    validator.validate(createProjectReactor("foo", def -> def.setVersion("2017-10-16")));
+    validator.validate(createProjectReactor("foo", def -> def.setVersion(repeat("a", 100))));
+  }
+
+  @Test
+  public void fail_with_too_long_version() {
+    ProjectReactor reactor = createProjectReactor("foo", def -> def.setVersion(repeat("a", 101)));
+
+    thrown.expect(MessageException.class);
+    thrown.expectMessage("\"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa\" is not a valid version name for module \"foo\". " +
+      "The maximum length for version numbers is 100 characters.");
+
+    validator.validate(reactor);
   }
 
   private ProjectReactor createProjectReactor(String projectKey, String branch) {
+    return createProjectReactor(projectKey, def -> def
+      .setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, branch));
+  }
+
+  private ProjectReactor createProjectReactor(String projectKey, Consumer<ProjectDefinition>... consumers) {
     ProjectDefinition def = ProjectDefinition.create()
-      .setProperty(CoreProperties.PROJECT_KEY_PROPERTY, projectKey)
-      .setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, branch);
+      .setProperty(CoreProperties.PROJECT_KEY_PROPERTY, projectKey);
+    Arrays.stream(consumers).forEach(c -> c.accept(def));
     return new ProjectReactor(def);
   }
-
 }