aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2015-08-24 08:23:42 +0200
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>2015-08-24 10:38:51 +0200
commitce39ae27e9fdcab9b379bf5d9eb552e78e0d9416 (patch)
tree3bb3773cf0b728ef4724fee9f26199f5879c3ff3
parent0e271c15e6aa0e77fb1edc1ba42d0589948d141d (diff)
downloadsonarqube-ce39ae27e9fdcab9b379bf5d9eb552e78e0d9416.tar.gz
sonarqube-ce39ae27e9fdcab9b379bf5d9eb552e78e0d9416.zip
SONAR-6502 WS permissions/add_group_to_template add a group to a permission template
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionRequestValidator.java (renamed from server/sonar-server/src/main/java/org/sonar/server/permission/PermissionValueValidator.java)29
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateUpdater.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java14
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java109
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java65
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java4
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java3
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java2
-rw-r--r--server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java17
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java241
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java2
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java5
-rw-r--r--server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java5
-rw-r--r--sonar-db/src/main/java/org/sonar/core/permission/ProjectPermissions.java4
-rw-r--r--sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java31
-rw-r--r--sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml19
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/security/DefaultGroups.java4
19 files changed, 479 insertions, 84 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionValueValidator.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionRequestValidator.java
index e8a4a2d92f0..9ce5d35934b 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionValueValidator.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionRequestValidator.java
@@ -20,26 +20,31 @@
package org.sonar.server.permission;
-import org.sonar.core.permission.ProjectPermissions;
+import javax.annotation.Nullable;
import org.sonar.core.permission.GlobalPermissions;
-import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.core.permission.ProjectPermissions;
+
+import static java.lang.String.format;
+import static org.sonar.api.security.DefaultGroups.isAnyone;
+import static org.sonar.server.ws.WsUtils.checkRequest;
-public class PermissionValueValidator {
- private PermissionValueValidator() {
+public class PermissionRequestValidator {
+ private PermissionRequestValidator() {
// static methods only
}
public static void validateProjectPermission(String permission) {
- if (!ProjectPermissions.ALL.contains(permission)) {
- throw new BadRequestException(String.format("The 'permission' parameter for project permissions must be one of %s. '%s' was passed.", ProjectPermissions.ALL_ON_ONE_LINE,
- permission));
- }
+ checkRequest(ProjectPermissions.ALL.contains(permission),
+ format("The 'permission' parameter for project permissions must be one of %s. '%s' was passed.", ProjectPermissions.ALL_ON_ONE_LINE, permission));
}
public static void validateGlobalPermission(String permission) {
- if (!GlobalPermissions.ALL.contains(permission)) {
- throw new BadRequestException(String.format("The 'permission' parameter for global permissions must be one of %s. '%s' was passed.", GlobalPermissions.ALL_ON_ONE_LINE,
- permission));
- }
+ checkRequest(GlobalPermissions.ALL.contains(permission),
+ format("The 'permission' parameter for global permissions must be one of %s. '%s' was passed.", GlobalPermissions.ALL_ON_ONE_LINE, permission));
+ }
+
+ public static void validateNotAnyoneAndAdminPermission(String permission, @Nullable String groupName) {
+ checkRequest(!GlobalPermissions.SYSTEM_ADMIN.equals(permission) || !isAnyone(groupName),
+ String.format("It is not possible to add the '%s' permission to the '%s' group.", permission, groupName));
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateUpdater.java
index 4f3970f642b..28063e8bdaf 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateUpdater.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionTemplateUpdater.java
@@ -30,7 +30,7 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.user.UserSession;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.PermissionValueValidator.validateProjectPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPermission;
/**
* @deprecated since 5.2 can be removed when Ruby doesn't rely on PermissionTemplateService
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java
index d1f32625034..27be8f1c8ae 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/PermissionUpdater.java
@@ -23,7 +23,6 @@ package org.sonar.server.permission;
import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nullable;
-import org.sonar.api.security.DefaultGroups;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
@@ -36,7 +35,9 @@ import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.issue.index.IssueAuthorizationIndexer;
import org.sonar.server.user.UserSession;
+import static org.sonar.api.security.DefaultGroups.isAnyone;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkProjectAdminUserByComponentKey;
+import static org.sonar.server.permission.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
public class PermissionUpdater {
@@ -114,7 +115,7 @@ public class PermissionUpdater {
Long targetedGroup = getTargetedGroup(session, permissionChange.groupName());
String permission = permissionChange.permission();
if (Operation.ADD == operation) {
- checkNotAnyoneAndAdmin(permission, permissionChange.groupName());
+ validateNotAnyoneAndAdminPermission(permission, permissionChange.groupName());
permissionRepository.insertGroupPermission(componentId, targetedGroup, permission, session);
} else {
checkAdminUsersExistOutsideTheRemovedGroup(session, permissionChange, targetedGroup);
@@ -123,13 +124,6 @@ public class PermissionUpdater {
return true;
}
- private static void checkNotAnyoneAndAdmin(String permission, String group) {
- if (GlobalPermissions.SYSTEM_ADMIN.equals(permission)
- && DefaultGroups.isAnyone(group)) {
- throw new BadRequestException(String.format("It is not possible to add the '%s' permission to the '%s' group.", permission, group));
- }
- }
-
private boolean applyChangeOnUser(DbSession session, Operation operation, PermissionChange permissionChange) {
Long componentId = getComponentId(session, permissionChange.componentKey());
checkProjectAdminUserByComponentKey(userSession, permissionChange.componentKey());
@@ -173,7 +167,7 @@ public class PermissionUpdater {
@Nullable
private Long getTargetedGroup(DbSession session, String group) {
- if (DefaultGroups.isAnyone(group)) {
+ if (isAnyone(group)) {
return null;
} else {
GroupDto groupDto = dbClient.groupDao().selectByName(session, group);
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java
new file mode 100644
index 00000000000..6e35f17edd0
--- /dev/null
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupToTemplateAction.java
@@ -0,0 +1,109 @@
+/*
+ * 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 javax.annotation.Nullable;
+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.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+import org.sonar.server.user.UserSession;
+
+import static org.sonar.api.security.DefaultGroups.ANYONE;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
+import static org.sonar.server.permission.PermissionRequestValidator.validateNotAnyoneAndAdminPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPermission;
+import static org.sonar.server.permission.ws.Parameters.PARAM_GROUP_ID;
+import static org.sonar.server.permission.ws.Parameters.PARAM_GROUP_NAME;
+import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_KEY;
+import static org.sonar.server.permission.ws.Parameters.createGroupIdParameter;
+import static org.sonar.server.permission.ws.Parameters.createGroupNameParameter;
+import static org.sonar.server.permission.ws.Parameters.createPermissionParameter;
+import static org.sonar.server.permission.ws.Parameters.createTemplateKeyParameter;
+
+public class AddGroupToTemplateAction implements PermissionsWsAction {
+ private final DbClient dbClient;
+ private final PermissionDependenciesFinder dependenciesFinder;
+ private final UserSession userSession;
+
+ public AddGroupToTemplateAction(DbClient dbClient, PermissionDependenciesFinder dependenciesFinder, UserSession userSession) {
+ this.dbClient = dbClient;
+ this.dependenciesFinder = dependenciesFinder;
+ this.userSession = userSession;
+ }
+
+ @Override
+ public void define(WebService.NewController context) {
+ WebService.NewAction action = context
+ .createAction("add_group_to_template")
+ .setPost(true)
+ .setSince("5.2")
+ .setDescription("Add a group to a permission template.<br /> " +
+ "The group id or group name must be provided. <br />" +
+ "It requires administration permissions to access.")
+ .setHandler(this);
+
+ createTemplateKeyParameter(action);
+ createPermissionParameter(action);
+ createGroupIdParameter(action);
+ createGroupNameParameter(action);
+ }
+
+ @Override
+ public void handle(Request wsRequest, Response wsResponse) throws Exception {
+ checkGlobalAdminUser(userSession);
+
+ String templateKey = wsRequest.mandatoryParam(PARAM_TEMPLATE_KEY);
+ String permission = wsRequest.mandatoryParam(PARAM_PERMISSION);
+ Long groupIdParam = wsRequest.paramAsLong(PARAM_GROUP_ID);
+ String groupName = wsRequest.param(PARAM_GROUP_NAME);
+
+ DbSession dbSession = dbClient.openSession(false);
+ try {
+ validateProjectPermission(permission);
+ validateNotAnyoneAndAdminPermission(permission, groupName);
+
+ PermissionTemplateDto template = dependenciesFinder.getTemplate(templateKey);
+ GroupDto group = dependenciesFinder.getGroup(dbSession, groupIdParam, groupName);
+
+ if (!groupAlreadyAdded(dbSession, template.getId(), group, permission)) {
+ Long groupId = group == null ? null : group.getId();
+ dbClient.permissionTemplateDao().insertGroupPermission(dbSession, template.getId(), groupId, permission);
+ }
+ } finally {
+ dbClient.closeSession(dbSession);
+ }
+
+ wsResponse.noContent();
+ }
+
+ private boolean groupAlreadyAdded(DbSession dbSession, long templateId, @Nullable GroupDto group, String permission) {
+ String groupName = group == null ? ANYONE : group.getName();
+ PermissionQuery permissionQuery = PermissionQuery.builder().membership(IN).permission(permission).build();
+ return dbClient.permissionTemplateDao().hasGroup(dbSession, permissionQuery, templateId, groupName);
+ }
+}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java
index 78b5e7ec988..01ae1255d4c 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserToTemplateAction.java
@@ -36,7 +36,7 @@ import org.sonar.server.user.UserSession;
import static com.google.common.collect.FluentIterable.from;
import static org.sonar.db.user.GroupMembershipQuery.IN;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.PermissionValueValidator.validateProjectPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPermission;
import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_KEY;
import static org.sonar.server.permission.ws.Parameters.PARAM_USER_LOGIN;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java
index 80db297ef98..32d73c48a08 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionDependenciesFinder.java
@@ -22,6 +22,7 @@ package org.sonar.server.permission.ws;
import com.google.common.base.Optional;
import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
@@ -29,11 +30,12 @@ import org.sonar.db.permission.PermissionTemplateDto;
import org.sonar.db.user.GroupDto;
import org.sonar.db.user.UserDto;
import org.sonar.server.component.ComponentFinder;
-import org.sonar.server.exceptions.BadRequestException;
-import static com.google.common.base.Preconditions.checkNotNull;
+import static java.lang.String.format;
import static org.sonar.api.security.DefaultGroups.ANYONE;
import static org.sonar.api.security.DefaultGroups.isAnyone;
+import static org.sonar.server.ws.WsUtils.checkFound;
+import static org.sonar.server.ws.WsUtils.checkRequest;
public class PermissionDependenciesFinder {
private final DbClient dbClient;
@@ -56,57 +58,44 @@ public class PermissionDependenciesFinder {
}
String getGroupName(DbSession dbSession, PermissionRequest request) {
- if (isAnyone(request.groupName())) {
- return ANYONE;
+ GroupDto group = getGroup(dbSession, request.groupId(), request.groupName());
+
+ return group == null ? ANYONE : group.getName();
+ }
+
+ /**
+ *
+ * @return null if it's the anyone group
+ */
+ @CheckForNull
+ GroupDto getGroup(DbSession dbSession, @Nullable Long groupId, @Nullable String groupName) {
+ checkRequest(groupId != null ^ groupName != null, "Group name or group id must be provided, not both.");
+ if (isAnyone(groupName)) {
+ return null;
}
GroupDto group = null;
- Long groupId = request.groupId();
if (groupId != null) {
- group = dbClient.groupDao().selectById(dbSession, groupId);
- if (group == null) {
- throw new BadRequestException(String.format("Group with id '%d' is not found", groupId));
- }
+ group = checkFound(dbClient.groupDao().selectById(dbSession, groupId),
+ format("Group with id '%d' is not found", groupId));
}
- String groupName = request.groupName();
if (groupName != null) {
- group = dbClient.groupDao().selectByName(dbSession, groupName);
- if (group == null) {
- throw new BadRequestException(String.format("Group with name '%s' is not found", groupName));
- }
- }
-
- return checkNotNull(group).getName();
- }
-
- @CheckForNull
- Long getGroupId(DbSession dbSession, String groupName) {
- if (isAnyone(groupName)) {
- return null;
+ group = checkFound(dbClient.groupDao().selectByName(dbSession, groupName),
+ format("Group with name '%s' is not found", groupName));
}
- GroupDto group = dbClient.groupDao().selectByName(dbSession, groupName);
- if (group == null) {
- throw new BadRequestException(String.format("Group with name '%s' is not found", groupName));
- }
- return group.getId();
+ return group;
}
UserDto getUser(DbSession dbSession, String userLogin) {
- UserDto user = dbClient.userDao().selectActiveUserByLogin(dbSession, userLogin);
- if (user == null) {
- throw new BadRequestException(String.format("User with login '%s' is not found'", userLogin));
- }
- return user;
+ return checkFound(dbClient.userDao().selectActiveUserByLogin(dbSession, userLogin),
+ format("User with login '%s' is not found'", userLogin));
}
PermissionTemplateDto getTemplate(String templateKey) {
- PermissionTemplateDto permissionTemplate = dbClient.permissionTemplateDao().selectTemplateByKey(templateKey);
- if (permissionTemplate == null) {
- throw new BadRequestException(String.format("Permission template with key '%s' is not found", templateKey));
- }
- return permissionTemplate;
+ return checkFound(dbClient.permissionTemplateDao().selectTemplateByKey(templateKey),
+ format("Permission template with key '%s' is not found", templateKey));
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java
index d043ea3a942..a6a87a7106d 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java
@@ -34,8 +34,8 @@ import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
import static org.sonar.server.permission.ws.Parameters.PARAM_PROJECT_KEY;
import static org.sonar.server.permission.ws.Parameters.PARAM_PROJECT_UUID;
import static org.sonar.server.permission.ws.Parameters.PARAM_USER_LOGIN;
-import static org.sonar.server.permission.PermissionValueValidator.validateGlobalPermission;
-import static org.sonar.server.permission.PermissionValueValidator.validateProjectPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateGlobalPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPermission;
import static org.sonar.server.ws.WsUtils.checkRequest;
class PermissionRequest {
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
index 18bf09ceddf..f7434324cbd 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionsWsModule.java
@@ -39,6 +39,7 @@ public class PermissionsWsModule extends Module {
SearchProjectPermissionsDataLoader.class,
PermissionDependenciesFinder.class,
AddUserToTemplateAction.class,
- RemoveUserFromTemplateAction.class);
+ RemoveUserFromTemplateAction.class,
+ AddGroupToTemplateAction.class);
}
}
diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java
index cdd5afe0772..7b2857e21ef 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserFromTemplateAction.java
@@ -30,7 +30,7 @@ import org.sonar.db.user.UserDto;
import org.sonar.server.user.UserSession;
import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobalAdminUser;
-import static org.sonar.server.permission.PermissionValueValidator.validateProjectPermission;
+import static org.sonar.server.permission.PermissionRequestValidator.validateProjectPermission;
import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_KEY;
import static org.sonar.server.permission.ws.Parameters.PARAM_USER_LOGIN;
diff --git a/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java b/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java
index 707cbbde6c5..b96a67b7235 100644
--- a/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java
+++ b/server/sonar-server/src/main/java/org/sonar/server/ws/WsUtils.java
@@ -28,6 +28,7 @@ import org.sonar.api.server.ws.Response;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.util.ProtobufJsonFormat;
import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.plugins.MimeTypes;
public class WsUtils {
@@ -56,9 +57,21 @@ public class WsUtils {
/**
* @throws BadRequestException
*/
- public static void checkRequest(boolean expression, String errorMessage) {
+ public static void checkRequest(boolean expression, String message) {
if (!expression) {
- throw new BadRequestException(errorMessage);
+ throw new BadRequestException(message);
}
}
+
+ /**
+ * @throws NotFoundException if the value if null
+ * @return the value
+ */
+ public static <T> T checkFound(T value, String message) {
+ if (value == null) {
+ throw new NotFoundException(message);
+ }
+
+ return value;
+ }
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java
new file mode 100644
index 00000000000..221fbfcf76e
--- /dev/null
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupToTemplateActionTest.java
@@ -0,0 +1,241 @@
+/*
+ * 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 com.google.common.base.Function;
+import java.util.List;
+import javax.annotation.Nonnull;
+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.utils.System2;
+import org.sonar.api.web.UserRole;
+import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.db.DbClient;
+import org.sonar.db.DbSession;
+import org.sonar.db.DbTester;
+import org.sonar.db.permission.GroupWithPermissionDto;
+import org.sonar.db.permission.PermissionQuery;
+import org.sonar.db.permission.PermissionTemplateDto;
+import org.sonar.db.user.GroupDto;
+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.tester.UserSessionRule;
+import org.sonar.server.ws.TestRequest;
+import org.sonar.server.ws.WsActionTester;
+import org.sonar.test.DbTests;
+
+import static com.google.common.collect.FluentIterable.from;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.sonar.api.security.DefaultGroups.ANYONE;
+import static org.sonar.api.web.UserRole.ADMIN;
+import static org.sonar.api.web.UserRole.CODEVIEWER;
+import static org.sonar.api.web.UserRole.ISSUE_ADMIN;
+import static org.sonar.db.permission.PermissionTemplateTesting.newPermissionTemplateDto;
+import static org.sonar.db.user.GroupMembershipQuery.IN;
+import static org.sonar.db.user.GroupTesting.newGroupDto;
+import static org.sonar.server.permission.ws.Parameters.PARAM_GROUP_ID;
+import static org.sonar.server.permission.ws.Parameters.PARAM_PERMISSION;
+import static org.sonar.server.permission.ws.Parameters.PARAM_TEMPLATE_KEY;
+
+@Category(DbTests.class)
+public class AddGroupToTemplateActionTest {
+
+ private static final String GROUP_NAME = "group-name";
+ @Rule
+ public DbTester db = DbTester.create(System2.INSTANCE);
+ @Rule
+ public ExpectedException expectedException = ExpectedException.none();
+ @Rule
+ public UserSessionRule userSession = UserSessionRule.standalone();
+
+ WsActionTester ws;
+ DbClient dbClient;
+ DbSession dbSession;
+ GroupDto group;
+ PermissionTemplateDto permissionTemplate;
+
+ @Before
+ public void setUp() {
+ dbClient = db.getDbClient();
+ dbSession = db.getSession();
+ userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
+
+ PermissionDependenciesFinder dependenciesFinder = new PermissionDependenciesFinder(dbClient, new ComponentFinder(dbClient));
+ ws = new WsActionTester(new AddGroupToTemplateAction(dbClient, dependenciesFinder, userSession));
+
+ group = insertGroup(newGroupDto().setName(GROUP_NAME));
+ permissionTemplate = insertPermissionTemplate(newPermissionTemplateDto());
+ commit();
+ }
+
+ @Test
+ public void add_group_to_template() {
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+
+ assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
+ }
+
+ @Test
+ public void add_with_group_id() {
+ ws.newRequest()
+ .setParam(PARAM_TEMPLATE_KEY, permissionTemplate.getKee())
+ .setParam(PARAM_PERMISSION, CODEVIEWER)
+ .setParam(PARAM_GROUP_ID, String.valueOf(group.getId()))
+ .execute();
+
+ assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(GROUP_NAME);
+ }
+
+ @Test
+ public void does_not_add_a_group_twice() {
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), ISSUE_ADMIN);
+
+ assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), ISSUE_ADMIN)).containsExactly(GROUP_NAME);
+ }
+
+ @Test
+ public void add_anyone_group_to_template() {
+ newRequest(ANYONE, permissionTemplate.getKee(), CODEVIEWER);
+
+ assertThat(getGroupNamesInTemplateAndPermission(permissionTemplate.getId(), CODEVIEWER)).containsExactly(ANYONE);
+ }
+
+ @Test
+ public void fail_if_add_anyone_group_to_admin_permission() {
+ expectedException.expect(BadRequestException.class);
+ expectedException.expectMessage(String.format("It is not possible to add the '%s' permission to the '%s' group.", UserRole.ADMIN, ANYONE));
+
+ newRequest(ANYONE, permissionTemplate.getKee(), ADMIN);
+ }
+
+ @Test
+ public void fail_if_not_a_project_permission() {
+ expectedException.expect(BadRequestException.class);
+
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), GlobalPermissions.PREVIEW_EXECUTION);
+ }
+
+ @Test
+ public void fail_if_insufficient_privileges() {
+ expectedException.expect(ForbiddenException.class);
+ userSession.setGlobalPermissions(GlobalPermissions.QUALITY_PROFILE_ADMIN);
+
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+ }
+
+ @Test
+ public void fail_if_not_logged_in() {
+ expectedException.expect(UnauthorizedException.class);
+ userSession.anonymous();
+
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), CODEVIEWER);
+ }
+
+ @Test
+ public void fail_if_group_params_missing() {
+ expectedException.expect(BadRequestException.class);
+
+ newRequest(null, permissionTemplate.getKee(), CODEVIEWER);
+ }
+
+ @Test
+ public void fail_if_permission_missing() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ newRequest(GROUP_NAME, permissionTemplate.getKee(), null);
+ }
+
+ @Test
+ public void fail_if_template_key_missing() {
+ expectedException.expect(IllegalArgumentException.class);
+
+ newRequest(GROUP_NAME, null, CODEVIEWER);
+ }
+
+ @Test
+ public void fail_if_group_does_not_exist() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Group with name 'unknown-group-name' is not found");
+
+ newRequest("unknown-group-name", permissionTemplate.getKee(), CODEVIEWER);
+ }
+
+ @Test
+ public void fail_if_template_key_does_not_exist() {
+ expectedException.expect(NotFoundException.class);
+ expectedException.expectMessage("Permission template with key 'unknown-key' is not found");
+
+ newRequest(GROUP_NAME, "unknown-key", CODEVIEWER);
+ }
+
+ private void newRequest(@Nullable String groupName, @Nullable String templateKey, @Nullable String permission) {
+ TestRequest request = ws.newRequest();
+ if (groupName != null) {
+ request.setParam(Parameters.PARAM_GROUP_NAME, groupName);
+ }
+ if (templateKey != null) {
+ request.setParam(PARAM_TEMPLATE_KEY, templateKey);
+ }
+ if (permission != null) {
+ request.setParam(Parameters.PARAM_PERMISSION, permission);
+ }
+
+ request.execute();
+ }
+
+ private void commit() {
+ dbSession.commit();
+ }
+
+ private GroupDto insertGroup(GroupDto groupDto) {
+ return dbClient.groupDao().insert(dbSession, groupDto);
+ }
+
+ private PermissionTemplateDto insertPermissionTemplate(PermissionTemplateDto permissionTemplate) {
+ return dbClient.permissionTemplateDao().insertPermissionTemplate(permissionTemplate.getName(), permissionTemplate.getDescription(), permissionTemplate.getKeyPattern());
+ }
+
+ private List<String> getGroupNamesInTemplateAndPermission(long templateId, String permission) {
+ PermissionQuery permissionQuery = PermissionQuery.builder().permission(permission).membership(IN).build();
+ return from(dbClient.permissionTemplateDao()
+ .selectGroups(dbSession, permissionQuery, templateId))
+ .transform(GroupWithPermissionToGroupName.INSTANCE)
+ .toList();
+ }
+
+ private enum GroupWithPermissionToGroupName implements Function<GroupWithPermissionDto, String> {
+ INSTANCE;
+
+ @Override
+ public String apply(@Nonnull GroupWithPermissionDto groupWithPermission) {
+ return groupWithPermission.getName();
+ }
+
+ }
+}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java
index 957fdcf2691..a4fdf5f09cc 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserToTemplateActionTest.java
@@ -41,6 +41,7 @@ import org.sonar.db.user.UserDto;
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.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
@@ -147,7 +148,7 @@ public class AddUserToTemplateActionTest {
@Test
public void fail_if_user_does_not_exist() {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
expectedException.expectMessage("User with login 'unknown-login' is not found");
newRequest("unknown-login", permissionTemplate.getKee(), CODEVIEWER);
@@ -155,7 +156,7 @@ public class AddUserToTemplateActionTest {
@Test
public void fail_if_template_key_does_not_exist() {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Permission template with key 'unknown-key' is not found");
newRequest(USER_LOGIN, "unknown-key", CODEVIEWER);
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
index b609653ed9d..cabe737a907 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/PermissionsWsModuleTest.java
@@ -30,6 +30,6 @@ public class PermissionsWsModuleTest {
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new PermissionsWsModule().configure(container);
- assertThat(container.size()).isEqualTo(16);
+ assertThat(container.size()).isEqualTo(17);
}
}
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java
index 016cf0aab0d..4e85fdb1efe 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveGroupActionTest.java
@@ -35,6 +35,7 @@ import org.sonar.db.component.ComponentDto;
import org.sonar.db.user.GroupDto;
import org.sonar.server.component.ComponentFinder;
import org.sonar.server.exceptions.BadRequestException;
+import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.exceptions.ServerException;
import org.sonar.server.permission.PermissionChange;
import org.sonar.server.permission.PermissionUpdater;
@@ -144,7 +145,7 @@ public class RemoveGroupActionTest {
@Test
public void fail_when_project_does_not_exist() throws Exception {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
newRequest()
.setParam(PARAM_GROUP_NAME, "sonar-administrators")
@@ -207,7 +208,7 @@ public class RemoveGroupActionTest {
@Test
public void fail_when_group_id_does_not_exist() throws Exception {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Group with id '42' is not found");
newRequest()
diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java
index 080a7b1e0f3..93bb60e77af 100644
--- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java
+++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserFromTemplateActionTest.java
@@ -41,6 +41,7 @@ import org.sonar.db.user.UserDto;
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.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
@@ -171,7 +172,7 @@ public class RemoveUserFromTemplateActionTest {
@Test
public void fail_if_user_does_not_exist() {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
expectedException.expectMessage("User with login 'unknown-login' is not found");
newRequest("unknown-login", permissionTemplate.getKee(), DEFAULT_PERMISSION);
@@ -179,7 +180,7 @@ public class RemoveUserFromTemplateActionTest {
@Test
public void fail_if_template_key_does_not_exist() {
- expectedException.expect(BadRequestException.class);
+ expectedException.expect(NotFoundException.class);
expectedException.expectMessage("Permission template with key 'unknown-key' is not found");
newRequest(USER_LOGIN, "unknown-key", DEFAULT_PERMISSION);
diff --git a/sonar-db/src/main/java/org/sonar/core/permission/ProjectPermissions.java b/sonar-db/src/main/java/org/sonar/core/permission/ProjectPermissions.java
index e7365f8232b..26e86f41ff3 100644
--- a/sonar-db/src/main/java/org/sonar/core/permission/ProjectPermissions.java
+++ b/sonar-db/src/main/java/org/sonar/core/permission/ProjectPermissions.java
@@ -31,6 +31,10 @@ import org.sonar.api.web.UserRole;
*/
public final class ProjectPermissions {
+ private ProjectPermissions() {
+ // static constants only
+ }
+
/**
* All the component permissions values, ordered from {@link UserRole#USER} to {@link UserRole#CODEVIEWER}.
*/
diff --git a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
index b5c58686816..1170be201d1 100644
--- a/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
+++ b/sonar-db/src/main/java/org/sonar/db/permission/PermissionTemplateDao.java
@@ -103,11 +103,22 @@ public class PermissionTemplateDao implements Dao {
}
}
- public int countGroups(DbSession session, PermissionQuery query, Long templateId) {
+ public int countGroups(DbSession session, PermissionQuery query, long templateId) {
+ return countGroups(session, query, templateId, null);
+ }
+
+ private int countGroups(DbSession session, PermissionQuery query, long templateId, @Nullable String groupName) {
Map<String, Object> parameters = groupsParamaters(query, templateId);
+ if (groupName != null) {
+ parameters.put("groupName", groupName.toUpperCase());
+ }
return mapper(session).countGroups(parameters);
}
+ public boolean hasGroup(DbSession session, PermissionQuery query, long templateId, String groupName) {
+ return countGroups(session, query, templateId, groupName) > 0;
+ }
+
private static Map<String, Object> groupsParamaters(PermissionQuery query, Long templateId) {
Map<String, Object> params = newHashMap();
params.put(QUERY_PARAMETER, query);
@@ -266,19 +277,23 @@ public class PermissionTemplateDao implements Dao {
}
public void insertGroupPermission(Long templateId, @Nullable Long groupId, String permission) {
+ DbSession session = myBatis.openSession(false);
+ try {
+ insertGroupPermission(session, templateId, groupId, permission);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
+
+ public void insertGroupPermission(DbSession session, Long templateId, @Nullable Long groupId, String permission) {
PermissionTemplateGroupDto permissionTemplateGroup = new PermissionTemplateGroupDto()
.setTemplateId(templateId)
.setPermission(permission)
.setGroupId(groupId)
.setCreatedAt(now())
.setUpdatedAt(now());
- SqlSession session = myBatis.openSession(false);
- try {
- mapper(session).insertGroupPermission(permissionTemplateGroup);
- session.commit();
- } finally {
- MyBatis.closeQuietly(session);
- }
+ mapper(session).insertGroupPermission(permissionTemplateGroup);
+ session.commit();
}
public void deleteGroupPermission(Long templateId, @Nullable Long groupId, String permission) {
diff --git a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
index 260baeb1d90..ce3496d303f 100644
--- a/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
+++ b/sonar-db/src/main/resources/org/sonar/db/permission/PermissionTemplateMapper.xml
@@ -119,6 +119,14 @@
<if test="query.search() != null">
AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/')
</if>
+ <choose>
+ <when test="query.membership() == 'IN'">
+ AND groups.permission IS NOT NULL
+ </when>
+ <when test="query.membership() == 'OUT'">
+ AND groups.permission IS NULL
+ </when>
+ </choose>
</where>
ORDER BY groups.name
</select>
@@ -141,9 +149,20 @@
</where>
) groups
<where>
+ <if test="groupName!=null">
+ AND (UPPER(groups.name) LIKE #{groupName} ESCAPE '/')
+ </if>
<if test="query.search() != null">
AND (UPPER(groups.name) LIKE #{query.searchSql} ESCAPE '/')
</if>
+ <choose>
+ <when test="query.membership() == 'IN'">
+ AND groups.permission IS NOT NULL
+ </when>
+ <when test="query.membership() == 'OUT'">
+ AND groups.permission IS NULL
+ </when>
+ </choose>
</where>
</select>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/security/DefaultGroups.java b/sonar-plugin-api/src/main/java/org/sonar/api/security/DefaultGroups.java
index 2d9a4f1154c..8f07391bf7b 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/security/DefaultGroups.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/security/DefaultGroups.java
@@ -19,6 +19,8 @@
*/
package org.sonar.api.security;
+import javax.annotation.Nullable;
+
/**
* Name of the default user groups
*
@@ -32,7 +34,7 @@ public final class DefaultGroups {
public static final String ADMINISTRATORS = "sonar-administrators";
public static final String USERS = "sonar-users";
- public static boolean isAnyone(String groupName) {
+ public static boolean isAnyone(@Nullable String groupName) {
return ANYONE.equalsIgnoreCase(groupName);
}
}