public class DefaultPermissionTemplates {
public static final String DEFAULT_TEMPLATE_PROPERTY = "sonar.permission.template.default";
- private static final String DEFAULT_ROOT_QUALIFIER_TEMPLATE_PROPERTY = "sonar.permission.template.%s.default";
+ private static final String DEFAULT_ROOT_QUALIFIER_TEMPLATE_PATTERN = "sonar.permission.template.%s.default";
public static String defaultRootQualifierTemplateProperty(String qualifier) {
- return format(DEFAULT_ROOT_QUALIFIER_TEMPLATE_PROPERTY, qualifier);
+ return format(DEFAULT_ROOT_QUALIFIER_TEMPLATE_PATTERN, qualifier);
}
}
public void handle(Request wsRequest, Response wsResponse) throws Exception {
checkGlobalAdminUser(userSession);
- String templateKey = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
+ String templateUuid = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
validateProjectPermission(permission);
validateNotAnyoneAndAdminPermission(permission, group.name());
- PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateKey);
+ PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateUuid);
GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
if (!groupAlreadyAdded(dbSession, template.getId(), groupDto, permission)) {
public void handle(Request wsRequest, Response wsResponse) throws Exception {
checkGlobalAdminUser(userSession);
- String templateKey = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
+ String templateUuid = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
final String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
DbSession dbSession = dbClient.openSession(false);
try {
validateProjectPermission(permission);
- PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateKey);
+ PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateUuid);
UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
if (!isUserAlreadyAdded(dbSession, template.getId(), userLogin, permission)) {
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_ID;
-import static org.sonar.server.permission.ws.Parameters.createTemplateKeyParameter;
+import static org.sonar.server.permission.ws.Parameters.createTemplateIdParameter;
import static org.sonar.server.ws.WsUtils.checkRequest;
public class DeleteTemplateAction implements PermissionsWsAction {
.setPost(true)
.setHandler(this);
- createTemplateKeyParameter(action);
+ createTemplateIdParameter(action);
}
@Override
static final String PARAM_TEMPLATE_DESCRIPTION = "description";
static final String PARAM_TEMPLATE_PATTERN = "projectKeyPattern";
+ static final String PARAM_QUALIFIER = "qualifier";
+
private static final String PERMISSION_PARAM_DESCRIPTION = format("Permission" +
"<ul>" +
"<li>Possible values for global permissions: %s</li>" +
.setExampleValue("Permissions for all projects related to the financial service");
}
- static void createTemplateKeyParameter(NewAction action) {
+ static void createTemplateIdParameter(NewAction action) {
action.createParam(PARAM_TEMPLATE_ID)
.setRequired(true)
.setDescription("Key")
package org.sonar.server.permission.ws;
+import java.util.Set;
import java.util.regex.Pattern;
import java.util.regex.PatternSyntaxException;
import javax.annotation.Nullable;
import static org.apache.commons.lang.StringUtils.isBlank;
import static org.sonar.api.security.DefaultGroups.isAnyone;
import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.Parameters.PARAM_QUALIFIER;
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_PATTERN;
import static org.sonar.server.ws.WsUtils.checkRequest;
checkRequest(!isBlank(name), MSG_TEMPLATE_NAME_NOT_BLANK);
}
+ public static void validateQualifier(String qualifier, Set<String> rootQualifiers) {
+ checkRequest(rootQualifiers.contains(qualifier),
+ format("The '%s' parameter must be one of %s. '%s' was passed.", PARAM_QUALIFIER, rootQualifiers, qualifier));
+ }
+
public static void validateProjectPattern(@Nullable String projectPattern) {
if (isNullOrEmpty(projectPattern)) {
return;
UpdateTemplateAction.class,
DeleteTemplateAction.class,
ApplyTemplateAction.class,
+ SetDefaultTemplateAction.class,
// utility classes
PermissionChangeBuilder.class,
SearchProjectPermissionsDataLoader.class,
public void handle(Request wsRequest, Response wsResponse) throws Exception {
checkGlobalAdminUser(userSession);
- String templateKey = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
+ String templateUuid = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
WsGroupRef group = WsGroupRef.fromRequest(wsRequest);
try {
validateProjectPermission(permission);
- PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateKey);
+ PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateUuid);
GroupDto groupDto = dependenciesFinder.getGroup(dbSession, group);
Long groupId = groupDto == null ? null : groupDto.getId();
public void handle(Request wsRequest, Response wsResponse) throws Exception {
checkGlobalAdminUser(userSession);
- String templateKey = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
+ String templateUuid = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
String userLogin = wsRequest.mandatoryParam(PARAM_USER_LOGIN);
DbSession dbSession = dbClient.openSession(false);
try {
validateProjectPermission(permission);
- PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateKey);
+ PermissionTemplateDto template = dependenciesFinder.getTemplate(dbSession, templateUuid);
UserDto user = dependenciesFinder.getUser(dbSession, userLogin);
dbClient.permissionTemplateDao().deleteUserPermission(dbSession, template.getId(), user.getId(), permission);
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.permission.ws;
+
+import java.util.Set;
+import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.api.server.ws.WebService;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.server.platform.PersistentSettings;
+import org.sonar.server.user.UserSession;
+
+import static com.google.common.collect.FluentIterable.from;
+import static com.google.common.collect.Ordering.natural;
+import static java.lang.String.format;
+import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.ws.Parameters.PARAM_QUALIFIER;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_ID_EXPLICIT;
+import static org.sonar.server.permission.ws.Parameters.createExplicitTemplateId;
+import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
+import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
+
+public class SetDefaultTemplateAction implements PermissionsWsAction {
+ private final DbClient dbClient;
+ private final PermissionDependenciesFinder finder;
+ private final ResourceTypes resourceTypes;
+ private final PersistentSettings settings;
+ private final UserSession userSession;
+ private final I18n i18n;
+
+ public SetDefaultTemplateAction(DbClient dbClient, PermissionDependenciesFinder finder, ResourceTypes resourceTypes, PersistentSettings settings, UserSession userSession,
+ I18n i18n) {
+ this.dbClient = dbClient;
+ this.finder = finder;
+ this.resourceTypes = resourceTypes;
+ this.settings = settings;
+ this.userSession = userSession;
+ this.i18n = i18n;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context.createAction("set_default_template")
+ .setDescription("Set a permission template as default.<br />" +
+ "It requires administration permissions to access.")
+ .setPost(true)
+ .setSince("5.2")
+ .setHandler(this);
+
+ createExplicitTemplateId(action);
+
+ action.createParam(PARAM_QUALIFIER)
+ .setDescription("Project qualifier. Possible values are:")
+ .setDefaultValue(Qualifiers.PROJECT)
+ .setPossibleValues(getRootQualifiers());
+ }
+
+ @Override
+ public void handle(Request wsRequest, Response wsResponse) throws Exception {
+ checkGlobalAdminUser(userSession);
+
+ String templateUuid = wsRequest.mandatoryParam(PARAM_TEMPLATE_ID_EXPLICIT);
+ String qualifier = wsRequest.mandatoryParam(PARAM_QUALIFIER);
+
+ checkTemplateExists(templateUuid);
+ validateQualifier(qualifier, getRootQualifiers());
+ setDefaultTemplateUuid(templateUuid, qualifier);
+ wsResponse.noContent();
+ }
+
+ private Set<String> getRootQualifiers() {
+ return from(resourceTypes.getRoots())
+ .transform(RESOURCE_TYPE_TO_QUALIFIER)
+ .toSortedSet(natural());
+ }
+
+ private String buildRootQualifiersDescription() {
+ StringBuilder description = new StringBuilder();
+ description.append("<ul>");
+ String qualifierPattern = "<li>%s - %s</li>";
+ for (String qualifier : getRootQualifiers()) {
+ description.append(format(qualifierPattern, qualifier, i18n(qualifier)));
+ }
+ description.append("</ul>");
+
+ return description.toString();
+ }
+
+ private String i18n(String qualifier) {
+ String qualifiersPropertyPrefix = "qualifiers.";
+ return i18n.message(userSession.locale(), qualifiersPropertyPrefix + qualifier, "");
+ }
+
+ private void checkTemplateExists(String templateUuid) {
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ finder.getTemplate(dbSession, templateUuid);
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+ }
+
+ private void setDefaultTemplateUuid(String templateUuid, String qualifier) {
+ settings.saveProperty(defaultRootQualifierTemplateProperty(qualifier), templateUuid);
+ if (Qualifiers.PROJECT.equals(qualifier)) {
+ settings.saveProperty(DEFAULT_TEMPLATE_PROPERTY, templateUuid);
+ }
+ }
+}
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_NAME;
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_PATTERN;
import static org.sonar.server.permission.ws.Parameters.createTemplateDescriptionParameter;
-import static org.sonar.server.permission.ws.Parameters.createTemplateKeyParameter;
+import static org.sonar.server.permission.ws.Parameters.createTemplateIdParameter;
import static org.sonar.server.permission.ws.Parameters.createTemplateProjectKeyPatternParameter;
import static org.sonar.server.permission.ws.PermissionRequestValidator.MSG_TEMPLATE_WITH_SAME_NAME;
import static org.sonar.server.permission.ws.PermissionRequestValidator.validateProjectPattern;
.setPost(true)
.setHandler(this);
- createTemplateKeyParameter(action);
+ createTemplateIdParameter(action);
action.createParam(PARAM_TEMPLATE_NAME)
.setDescription("Name")
private final String key;
private WsProjectRef(Request wsRequest) {
- String uuid = wsRequest.param(PARAM_PROJECT_ID);
- String key = wsRequest.param(PARAM_PROJECT_KEY);
+ this.uuid = wsRequest.param(PARAM_PROJECT_ID);
+ this.key = wsRequest.param(PARAM_PROJECT_KEY);
checkRequest(uuid != null ^ key != null, "Project id or project key can be provided, not both.");
-
- this.uuid = uuid;
- this.key = key;
}
static Optional<WsProjectRef> optionalFromRequest(Request wsRequest) {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new PermissionsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(23);
+ assertThat(container.size()).isEqualTo(24);
}
}
--- /dev/null
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube 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.
+ *
+ * SonarQube 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.permission.ws;
+
+import java.util.List;
+import java.util.Properties;
+import javax.annotation.Nullable;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.resources.Qualifiers;
+import org.sonar.api.resources.ResourceType;
+import org.sonar.api.resources.ResourceTypes;
+import org.sonar.api.utils.System2;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.permission.PermissionTemplateTesting;
+import org.sonar.server.component.ComponentFinder;
+import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+import org.sonar.server.exceptions.UnauthorizedException;
+import org.sonar.server.i18n.I18nRule;
+import org.sonar.server.platform.PersistentSettings;
+import org.sonar.server.platform.ServerSettings;
+import org.sonar.server.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static java.util.Arrays.asList;
+import static java.util.Collections.singletonList;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.sonar.api.resources.Qualifiers.PROJECT;
+import static org.sonar.api.resources.Qualifiers.VIEW;
+import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
+import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
+import static org.sonar.server.permission.ws.Parameters.PARAM_QUALIFIER;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_ID_EXPLICIT;
+
+@Category(DbTests.class)
+public class SetDefaultTemplateActionTest {
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ I18nRule i18n = new I18nRule();
+
+ WsActionTester ws;
+ PersistentSettings persistentSettings;
+ ResourceTypes resourceTypes = mock(ResourceTypes.class);
+
+ PermissionTemplateDto template;
+
+ @Before
+ public void setUp() {
+ DbClient dbClient = db.getDbClient();
+ persistentSettings = new PersistentSettings(dbClient.propertiesDao(), new ServerSettings(new PropertyDefinitions(), new Properties()));
+ persistentSettings.saveProperty(DEFAULT_TEMPLATE_PROPERTY, "any-template-uuid");
+ persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(PROJECT), "any-template-uuid");
+ persistentSettings.saveProperty(defaultRootQualifierTemplateProperty(VIEW), "any-view-template-uuid");
+ persistentSettings.saveProperty(defaultRootQualifierTemplateProperty("DEV"), "any-dev-template-uuid");
+ when(resourceTypes.getRoots()).thenReturn(rootResourceTypes());
+ userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+ ws = new WsActionTester(new SetDefaultTemplateAction(
+ dbClient,
+ new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient)),
+ resourceTypes,
+ persistentSettings,
+ userSession, i18n));
+
+ template = dbClient.permissionTemplateDao().insert(db.getSession(), PermissionTemplateTesting.newPermissionTemplateDto().setUuid("permission-template-uuid"));
+ }
+
+ @Test
+ public void update_settings_of_default_and_qualifier_default_for_project_qualifier() {
+ // default value is project qualifier's value
+ String result = newRequest(template.getUuid(), null);
+
+ assertThat(result).isEmpty();
+ assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo(template.getUuid());
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo(template.getUuid());
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo("any-view-template-uuid");
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
+ }
+
+ @Test
+ public void update_settings_of_views_property() {
+ newRequest(template.getUuid(), VIEW);
+
+ assertThat(persistentSettings.getString(DEFAULT_TEMPLATE_PROPERTY)).isEqualTo("any-template-uuid");
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(PROJECT))).isEqualTo("any-template-uuid");
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty(VIEW))).isEqualTo(template.getUuid());
+ assertThat(persistentSettings.getString(defaultRootQualifierTemplateProperty("DEV"))).isEqualTo("any-dev-template-uuid");
+ }
+
+ @Test
+ public void fail_if_anonymous() {
+ expectedException.expect(UnauthorizedException.class);
+ userSession.anonymous();
+
+ newRequest(template.getUuid(), PROJECT);
+ }
+
+ @Test
+ public void fail_if_not_admin() {
+ expectedException.expect(ForbiddenException.class);
+ userSession.login().setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ newRequest(template.getUuid(), PROJECT);
+ }
+
+ @Test
+ public void fail_if_template_not_provided() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ newRequest(null, PROJECT);
+ }
+
+ @Test
+ public void fail_if_template_does_not_exist() {
+ expectedException.expect(NotFoundException.class);
+
+ newRequest("unknown-template-uuid", PROJECT);
+ }
+
+ @Test
+ public void fail_if_qualifier_is_not_root() {
+ expectedException.expect(BadRequestException.class);
+ when(resourceTypes.getRoots()).thenReturn(singletonList(ResourceType.builder(PROJECT).build()));
+
+ newRequest(template.getUuid(), VIEW);
+ }
+
+ private String newRequest(@Nullable String templateUuid, @Nullable String qualifier) {
+ TestRequest request = ws.newRequest();
+ if (templateUuid != null) {
+ request.setParam(PARAM_TEMPLATE_ID_EXPLICIT, templateUuid);
+ }
+ if (qualifier != null) {
+ request.setParam(PARAM_QUALIFIER, qualifier);
+ }
+
+ return request.execute().getInput();
+ }
+
+ private static List<ResourceType> rootResourceTypes() {
+ ResourceType project = ResourceType.builder(PROJECT).build();
+ ResourceType view = ResourceType.builder(Qualifiers.VIEW).build();
+ ResourceType dev = ResourceType.builder("DEV").build();
+
+ return asList(project, view, dev);
+ }
+}