*/
package org.sonar.db.permission.template;
+import java.util.function.Consumer;
import javax.annotation.Nullable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
ofNullable(portfoliosDefaultTemplate).map(PermissionTemplateDto::getUuid).orElse(null));
}
- public PermissionTemplateDto insertTemplate() {
- return insertTemplate(newPermissionTemplateDto());
+ @SafeVarargs
+ public final PermissionTemplateDto insertTemplate(Consumer<PermissionTemplateDto>... populators) {
+ return insertTemplate(newPermissionTemplateDto(populators));
}
public PermissionTemplateDto insertTemplate(PermissionTemplateDto template) {
package org.sonar.db.permission.template;
import java.util.Date;
+import java.util.function.Consumer;
import org.apache.commons.lang.math.RandomUtils;
import org.sonar.core.util.Uuids;
import org.sonar.db.permission.PermissionsTestHelper;
+import static java.util.Arrays.stream;
import static org.apache.commons.lang.RandomStringUtils.randomAlphanumeric;
import static org.apache.commons.lang.RandomStringUtils.randomAscii;
public class PermissionTemplateTesting {
- public static PermissionTemplateDto newPermissionTemplateDto() {
- return new PermissionTemplateDto()
+ @SafeVarargs
+ public static PermissionTemplateDto newPermissionTemplateDto(Consumer<PermissionTemplateDto>... populators) {
+ PermissionTemplateDto dto = new PermissionTemplateDto()
.setName(randomAlphanumeric(60))
.setDescription(randomAscii(500))
.setUuid(Uuids.create())
.setCreatedAt(new Date())
.setUpdatedAt(new Date());
+ stream(populators).forEach(p -> p.accept(dto));
+ return dto;
}
public static PermissionTemplateUserDto newPermissionTemplateUserDto() {
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.exceptions;
+
+ import com.google.common.base.MoreObjects;
+ import java.util.List;
+
+ import static java.net.HttpURLConnection.HTTP_BAD_REQUEST;
+ import static java.util.Collections.singletonList;
+
+/**
+ * Provided request is not valid due to Permission template matching key collision.
+ */
+public class TemplateMatchingKeyException extends ServerException {
+ private final transient List<String> errors;
+
+ public TemplateMatchingKeyException(String errorMessage) {
+ super(HTTP_BAD_REQUEST, errorMessage);
+ this.errors = singletonList(errorMessage);
+ }
+
+ public List<String> errors() {
+ return this.errors;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("errors", this.errors())
+ .toString();
+ }
+
+}
+
--- /dev/null
+/*
+ * SonarQube
+ * Copyright (C) 2009-2021 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.exceptions;
+
+import org.junit.Test;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class TemplateMatchingKeyExceptionTest {
+
+ @Test
+ public void testMethods() {
+ TemplateMatchingKeyException ex = new TemplateMatchingKeyException("error");
+
+ assertThat(ex).hasToString("TemplateMatchingKeyException{errors=[error]}");
+ }
+
+}
import org.sonar.db.user.UserId;
import org.sonar.server.es.ProjectIndexer;
import org.sonar.server.es.ProjectIndexers;
+import org.sonar.server.exceptions.TemplateMatchingKeyException;
import org.sonar.server.permission.DefaultTemplatesResolver.ResolvedDefaultTemplates;
import org.sonar.server.user.UserSession;
templatesNames.append(", ");
}
}
- throw new IllegalStateException(MessageFormat.format(
+ throw new TemplateMatchingKeyException(MessageFormat.format(
"The \"{0}\" key matches multiple permission templates: {1}."
+ " A system administrator must update these templates so that only one of them matches the key.",
componentKey,
package org.sonar.server.permission;
import java.util.List;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.db.user.UserDto;
import org.sonar.server.es.ProjectIndexers;
import org.sonar.server.es.TestProjectIndexers;
+import org.sonar.server.exceptions.TemplateMatchingKeyException;
import org.sonar.server.tester.UserSessionRule;
import static java.util.Collections.singletonList;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.sonar.api.resources.Qualifiers.APP;
import static org.sonar.api.resources.Qualifiers.PROJECT;
import static org.sonar.api.resources.Qualifiers.VIEW;
private final ProjectIndexers projectIndexers = new TestProjectIndexers();
private final PermissionTemplateService underTest = new PermissionTemplateService(dbTester.getDbClient(), projectIndexers, userSession, defaultTemplatesResolver,
new SequenceUuidFactory());
+ private ComponentDto privateProject;
@Test
public void apply_does_not_insert_permission_to_group_AnyOne_when_applying_template_on_private_project() {
checkWouldUserHaveScanPermission(null, false);
}
+ @Test
+ public void apply_permission_template_with_key_pattern_collision() {
+ final String key = "hi-test";
+ final String keyPattern = ".*-test";
+
+ Stream<PermissionTemplateDto> templates = Stream.of(
+ templateDb.insertTemplate(t -> t.setKeyPattern(keyPattern)),
+ templateDb.insertTemplate(t -> t.setKeyPattern(keyPattern))
+ );
+
+ String templateNames = templates
+ .map(PermissionTemplateDto::getName)
+ .sorted(String.CASE_INSENSITIVE_ORDER)
+ .map(x -> String.format("\"%s\"", x))
+ .collect(Collectors.joining(", "));
+
+ ComponentDto project = dbTester.components().insertPrivateProject(p -> p.setDbKey(key));
+
+ assertThatThrownBy(() -> underTest.applyDefaultToNewComponent(session, project, null))
+ .isInstanceOf(TemplateMatchingKeyException.class)
+ .hasMessageContaining("The \"%s\" key matches multiple permission templates: %s.", key, templateNames);
+ }
+
private void checkWouldUserHaveScanPermission(@Nullable String userUuid, boolean expectedResult) {
assertThat(underTest.wouldUserHaveScanPermissionWithDefaultTemplate(session, userUuid, "PROJECT_KEY"))
.isEqualTo(expectedResult);
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.text.JsonWriter;
-import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.BadConfigurationException;
+import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ServerException;
import org.sonarqube.ws.MediaTypes;