From aaa5554c0a8e5478ad94739933784bdb59d60270 Mon Sep 17 00:00:00 2001 From: Teryk Bellahsene Date: Tue, 11 Aug 2015 15:50:28 +0200 Subject: [PATCH] Improvements on all permissions/* WS - use PermissionRequest - add checks - improve WS descriptions --- .../server/permission/ws/AddGroupAction.java | 40 +-- .../server/permission/ws/AddUserAction.java | 49 ++-- .../server/permission/ws/GroupsAction.java | 68 ++---- .../permission/ws/PermissionRequest.java | 231 ++++++++++++++++++ .../permission/ws/PermissionWsCommons.java | 121 +++++---- .../permission/ws/RemoveGroupAction.java | 41 ++-- .../permission/ws/RemoveUserAction.java | 51 ++-- .../server/permission/ws/UsersAction.java | 61 ++--- .../java/org/sonar/server/ws/WsUtils.java | 10 + .../permission/ws/AddGroupActionTest.java | 40 ++- .../permission/ws/AddUserActionTest.java | 45 +++- .../permission/ws/GroupsActionTest.java | 24 ++ .../permission/ws/RemoveGroupActionTest.java | 28 ++- .../permission/ws/RemoveUserActionTest.java | 30 ++- .../server/permission/ws/UsersActionTest.java | 35 ++- 15 files changed, 604 insertions(+), 270 deletions(-) create mode 100644 server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java index a0f59e0d136..6e7ec7c6afc 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddGroupAction.java @@ -23,17 +23,17 @@ package org.sonar.server.permission.ws; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; +import org.sonar.server.permission.ws.PermissionRequest.Builder; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_ID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_NAME; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionWsCommons.createGroupIdParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createGroupNameParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; public class AddGroupAction implements PermissionsWsAction { @@ -60,33 +60,19 @@ public class AddGroupAction implements PermissionsWsAction { .setPost(true) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setDescription("Permission") - .setRequired(true) - .setPossibleValues(GlobalPermissions.ALL); - - action.createParam(PARAM_GROUP_NAME) - .setDescription("Group name or 'anyone' (whatever the case)") - .setExampleValue("sonar-administrators"); - - action.createParam(PARAM_GROUP_ID) - .setDescription("Group id") - .setExampleValue("42"); - - action.createParam(PARAM_PROJECT_UUID) - .setDescription("Project id") - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); - - action.createParam(PARAM_PROJECT_KEY) - .setDescription("Project key") - .setExampleValue("org.apache.hbas:hbase"); + createPermissionParameter(action); + createGroupNameParameter(action); + createGroupIdParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request request, Response response) throws Exception { DbSession dbSession = dbClient.openSession(false); try { - PermissionChange permissionChange = permissionWsCommons.buildGroupPermissionChange(dbSession, request); + PermissionRequest permissionRequest = new Builder(request).withGroup().build(); + PermissionChange permissionChange = permissionWsCommons.buildGroupPermissionChange(dbSession, permissionRequest); permissionUpdater.addPermission(permissionChange); } finally { dbClient.closeSession(dbSession); diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserAction.java index 8aff38fc470..525bb3a98c5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/AddUserAction.java @@ -23,23 +23,27 @@ package org.sonar.server.permission.ws; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; +import org.sonar.server.permission.ws.PermissionRequest.Builder; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_USER_LOGIN; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createUserLoginParameter; public class AddUserAction implements PermissionsWsAction { public static final String ACTION = "add_user"; + private final DbClient dbClient; private final PermissionUpdater permissionUpdater; private final PermissionWsCommons permissionWsCommons; - public AddUserAction(PermissionUpdater permissionUpdater, PermissionWsCommons permissionWsCommons) { + public AddUserAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsCommons permissionWsCommons) { + this.dbClient = dbClient; this.permissionUpdater = permissionUpdater; this.permissionWsCommons = permissionWsCommons; } @@ -54,30 +58,23 @@ public class AddUserAction implements PermissionsWsAction { .setPost(true) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setDescription("Permission") - .setRequired(true) - .setPossibleValues(GlobalPermissions.ALL); - - action.createParam(PARAM_USER_LOGIN) - .setRequired(true) - .setDescription("User login") - .setExampleValue("g.hopper"); - - action.createParam(PARAM_PROJECT_UUID) - .setDescription("Project id") - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); - - action.createParam(PARAM_PROJECT_KEY) - .setDescription("Project key") - .setExampleValue("org.apache.hbas:hbase"); + createPermissionParameter(action); + createUserLoginParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request request, Response response) throws Exception { - PermissionChange permissionChange = permissionWsCommons.buildUserPermissionChange(request); - permissionUpdater.addPermission(permissionChange); + DbSession dbSession = dbClient.openSession(false); + try { + PermissionRequest permissionRequest = new Builder(request).withUser().build(); + PermissionChange permissionChange = permissionWsCommons.buildUserPermissionChange(dbSession, permissionRequest); + permissionUpdater.addPermission(permissionChange); - response.noContent(); + response.noContent(); + } finally { + dbClient.closeSession(dbSession); + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java index 3343ade3b26..926f18c4b8a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/GroupsAction.java @@ -21,7 +21,6 @@ package org.sonar.server.permission.ws; import com.google.common.base.Optional; -import com.google.common.collect.ImmutableSortedSet; import com.google.common.io.Resources; import java.util.List; import org.sonar.api.server.ws.Request; @@ -29,22 +28,20 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.server.ws.WebService.SelectionMode; -import org.sonar.core.permission.ComponentPermissions; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.permission.GroupWithPermission; import org.sonar.db.component.ComponentDto; import org.sonar.db.permission.PermissionQuery; import org.sonar.server.permission.GroupWithPermissionQueryResult; import org.sonar.server.permission.PermissionFinder; +import org.sonar.server.permission.ws.PermissionRequest.Builder; import org.sonarqube.ws.Common; import org.sonarqube.ws.Permissions; import static com.google.common.base.Objects.firstNonNull; -import static org.sonar.core.permission.GlobalPermissions.DASHBOARD_SHARING; import static org.sonar.server.permission.PermissionQueryParser.toMembership; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class GroupsAction implements PermissionsWsAction { @@ -71,38 +68,24 @@ public class GroupsAction implements PermissionsWsAction { .setResponseExample(Resources.getResource(getClass(), "groups-example.json")) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setExampleValue(DASHBOARD_SHARING) - .setRequired(true) - .setPossibleValues(ImmutableSortedSet.naturalOrder() - .addAll(GlobalPermissions.ALL) - .addAll(ComponentPermissions.ALL) - .build()); - - action.createParam(PARAM_PROJECT_UUID) - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d") - .setDescription("Project id"); - - action.createParam(PARAM_PROJECT_KEY) - .setExampleValue("org.apache.hbas:hbase") - .setDescription("Project key"); + createPermissionParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request wsRequest, Response wsResponse) throws Exception { - int page = wsRequest.mandatoryParamAsInt(Param.PAGE); - int pageSize = wsRequest.mandatoryParamAsInt(Param.PAGE_SIZE); - - Optional project = permissionWsCommons.searchProject(wsRequest); + PermissionRequest request = new Builder(wsRequest).withPagination().build(); + Optional project = permissionWsCommons.searchProject(request); permissionWsCommons.checkPermissions(project); - PermissionQuery permissionQuery = buildPermissionQuery(wsRequest, project); - Permissions.GroupsResponse groupsResponse = groupsResponse(permissionQuery, page, pageSize); + PermissionQuery permissionQuery = buildPermissionQuery(request, project); + Permissions.GroupsResponse groupsResponse = groupsResponse(permissionQuery, request); writeProtobuf(groupsResponse, wsRequest, wsResponse); } - private Permissions.GroupsResponse groupsResponse(PermissionQuery permissionQuery, int page, int pageSize) { + private Permissions.GroupsResponse groupsResponse(PermissionQuery permissionQuery, PermissionRequest permissionRequest) { GroupWithPermissionQueryResult groupsResult = permissionFinder.findGroupsWithPermission(permissionQuery); List groupsWithPermission = groupsResult.groups(); @@ -128,32 +111,21 @@ public class GroupsAction implements PermissionsWsAction { groupsResponse.setPaging( paging - .setPageIndex(page) - .setPageSize(pageSize) + .setPageIndex(permissionRequest.page()) + .setPageSize(permissionRequest.pageSize()) .setTotal(groupsResult.total()) ); return groupsResponse.build(); } - private static PermissionQuery buildPermissionQuery(Request wsRequest, Optional project) { - String permission = wsRequest.mandatoryParam("permission"); - String selected = wsRequest.param(Param.SELECTED); - int page = wsRequest.mandatoryParamAsInt(Param.PAGE); - int pageSize = wsRequest.mandatoryParamAsInt(Param.PAGE_SIZE); - String query = wsRequest.param(Param.TEXT_QUERY); - if (query != null) { - selected = SelectionMode.ALL.value(); - } - + private static PermissionQuery buildPermissionQuery(PermissionRequest request, Optional project) { PermissionQuery.Builder permissionQuery = PermissionQuery.builder() - .permission(permission) - .pageIndex(page) - .pageSize(pageSize) - .membership(toMembership(firstNonNull(selected, SelectionMode.SELECTED.value()))); - if (query != null) { - permissionQuery.search(query); - } + .permission(request.permission()) + .pageIndex(request.page()) + .pageSize(request.pageSize()) + .membership(toMembership(firstNonNull(request.selected(), SelectionMode.SELECTED.value()))) + .search(request.query()); if (project.isPresent()) { permissionQuery.component(project.get().getKey()); } 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 new file mode 100644 index 00000000000..f2f366db05f --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionRequest.java @@ -0,0 +1,231 @@ +/* + * 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 org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.WebService.SelectionMode; +import org.sonar.core.permission.ComponentPermissions; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.server.exceptions.BadRequestException; + +import static org.sonar.api.server.ws.WebService.Param.PAGE; +import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE; +import static org.sonar.api.server.ws.WebService.Param.SELECTED; +import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY; +import static org.sonar.server.permission.ws.PermissionWsCommons.GLOBAL_PERMISSIONS_ONE_LINE; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_ID; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_NAME; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_USER_LOGIN; +import static org.sonar.server.permission.ws.PermissionWsCommons.PROJECT_PERMISSIONS_ONE_LINE; +import static org.sonar.server.ws.WsUtils.checkRequest; + +public class PermissionRequest { + private final String permission; + private final String userLogin; + private final Long groupId; + private final String groupName; + private final String projectUuid; + private final String projectKey; + private final boolean hasProject; + private final Integer page; + private final Integer pageSize; + private final String selected; + private final String query; + + private PermissionRequest(Builder builder) { + permission = builder._permission; + userLogin = builder._userLogin; + groupId = builder._groupId; + groupName = builder._groupName; + projectUuid = builder._projectUuid; + projectKey = builder._projectKey; + hasProject = builder._hasProject; + page = builder._page; + pageSize = builder._pageSize; + selected = builder._selected; + query = builder._query; + } + + public static class Builder { + + private final Request request; + + private boolean withUser; + private boolean withGroup; + private boolean withPagination; + + private String _permission; + private String _userLogin; + + private Long _groupId; + private String _groupName; + private String _projectUuid; + private String _projectKey; + private boolean _hasProject; + private Integer _page; + private Integer _pageSize; + private String _selected; + private String _query; + + public Builder(Request request) { + this.request = request; + } + + public PermissionRequest build() { + _permission = request.mandatoryParam(PermissionWsCommons.PARAM_PERMISSION); + setUserLogin(request); + setGroup(request); + setProject(request); + setPaging(request); + setSelected(request); + setQuery(request); + checkPermissionParameter(); + + return new PermissionRequest(this); + } + + public Builder withUser() { + this.withUser = true; + return this; + } + + public Builder withGroup() { + this.withGroup = true; + return this; + } + + public Builder withPagination() { + this.withPagination = true; + return this; + } + + private void setQuery(Request request) { + if (request.hasParam(TEXT_QUERY)) { + _query = request.param(TEXT_QUERY); + if (_query != null) { + _selected = SelectionMode.ALL.value(); + } + } + } + + private void setSelected(Request request) { + if (request.hasParam(SELECTED)) { + _selected = request.mandatoryParam(SELECTED); + } + } + + private void setPaging(Request request) { + if (withPagination) { + _page = request.mandatoryParamAsInt(PAGE); + _pageSize = request.mandatoryParamAsInt(PAGE_SIZE); + } + } + + private void setUserLogin(Request request) { + if (withUser) { + _userLogin = request.mandatoryParam(PARAM_USER_LOGIN); + } + } + + private void setGroup(Request request) { + if (withGroup) { + Long groupId = request.paramAsLong(PARAM_GROUP_ID); + String groupName = request.param(PARAM_GROUP_NAME); + checkRequest(groupId != null ^ groupName != null, "Group name or group id must be provided, not both."); + _groupId = groupId; + _groupName = groupName; + } + } + + private void setProject(Request request) { + if (request.hasParam(PARAM_PROJECT_UUID) || request.hasParam(PARAM_PROJECT_KEY)) { + String projectUuid = request.param(PARAM_PROJECT_UUID); + String projectKey = request.param(PARAM_PROJECT_KEY); + + if (projectUuid != null || projectKey != null) { + checkRequest(projectUuid != null ^ projectKey != null, "Project id or project key can be provided, not both."); + _projectUuid = projectUuid; + _projectKey = projectKey; + _hasProject = true; + } + } + } + + private void checkPermissionParameter() { + if (_hasProject) { + if (!ComponentPermissions.ALL.contains(_permission)) { + throw new BadRequestException(String.format("Incorrect value '%s' for project permissions. Values allowed: %s.", _permission, PROJECT_PERMISSIONS_ONE_LINE)); + } + } else { + if (!GlobalPermissions.ALL.contains(_permission)) { + throw new BadRequestException(String.format("Incorrect value '%s' for global permissions. Values allowed: %s.", _permission, GLOBAL_PERMISSIONS_ONE_LINE)); + } + } + } + + } + + public String permission() { + return permission; + } + + public String userLogin() { + return userLogin; + } + + public Long groupId() { + return groupId; + } + + public String groupName() { + return groupName; + } + + public String projectUuid() { + return projectUuid; + } + + public String projectKey() { + return projectKey; + } + + public Integer page() { + return page; + } + + public Integer pageSize() { + return pageSize; + } + + public String selected() { + return selected; + } + + public String query() { + return query; + } + + public boolean hasProject() { + return hasProject; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java index 1c76b21d769..a825a075c71 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/PermissionWsCommons.java @@ -22,8 +22,9 @@ package org.sonar.server.permission.ws; import com.google.common.base.Joiner; import com.google.common.base.Optional; +import com.google.common.collect.ImmutableSortedSet; import javax.annotation.Nullable; -import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.web.UserRole; import org.sonar.core.permission.ComponentPermissions; import org.sonar.core.permission.GlobalPermissions; @@ -32,7 +33,6 @@ import org.sonar.db.DbSession; 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.permission.PermissionChange; import org.sonar.server.user.UserSession; @@ -47,8 +47,19 @@ public class PermissionWsCommons { public static final String PARAM_PROJECT_UUID = "projectId"; public static final String PARAM_PROJECT_KEY = "projectKey"; public static final String PARAM_USER_LOGIN = "login"; - private static final String PROJECT_PERMISSIONS_ONE_LINE = Joiner.on(",").join(ComponentPermissions.ALL); - private static final String GLOBAL_PERMISSIONS_ONE_LINE = Joiner.on(",").join(GlobalPermissions.ALL); + static final String PROJECT_PERMISSIONS_ONE_LINE = Joiner.on(", ").join(ComponentPermissions.ALL); + static final String GLOBAL_PERMISSIONS_ONE_LINE = Joiner.on(", ").join(GlobalPermissions.ALL); + private static final String PERMISSION_PARAM_DESCRIPTION = String.format("Permission" + + "
    " + + "
  • Possible values for global permissions: %s
  • " + + "
  • Possible values for project permissions %s
  • " + + "
", + GLOBAL_PERMISSIONS_ONE_LINE, + PROJECT_PERMISSIONS_ONE_LINE); + private static final ImmutableSortedSet> POSSIBLE_PERMISSIONS = ImmutableSortedSet.naturalOrder() + .addAll(GlobalPermissions.ALL) + .addAll(ComponentPermissions.ALL) + .build(); private final DbClient dbClient; private final ComponentFinder componentFinder; @@ -61,7 +72,6 @@ public class PermissionWsCommons { } public String searchGroupName(DbSession dbSession, @Nullable String groupNameParam, @Nullable Long groupId) { - checkParameters(groupNameParam, groupId); if (groupNameParam != null) { return groupNameParam; } @@ -74,70 +84,41 @@ public class PermissionWsCommons { return group.getName(); } - public PermissionChange buildUserPermissionChange(Request request) { - String permission = request.mandatoryParam(PARAM_PERMISSION); - String userLogin = request.mandatoryParam(PARAM_USER_LOGIN); - - DbSession dbSession = dbClient.openSession(false); - try { - PermissionChange permissionChange = new PermissionChange() - .setPermission(permission) - .setUserLogin(userLogin); - addProjectToPermissionChange(dbSession, permissionChange, request.param(PARAM_PROJECT_UUID), request.param(PARAM_PROJECT_KEY)); - - return permissionChange; - } finally { - dbClient.closeSession(dbSession); - } + public PermissionChange buildUserPermissionChange(DbSession dbSession, PermissionRequest request) { + PermissionChange permissionChange = new PermissionChange() + .setPermission(request.permission()) + .setUserLogin(request.userLogin()); + addProjectToPermissionChange(dbSession, permissionChange, request); + return permissionChange; } - public PermissionChange buildGroupPermissionChange(DbSession dbSession, Request request) { - String permission = request.mandatoryParam(PARAM_PERMISSION); - String groupNameParam = request.param(PARAM_GROUP_NAME); - Long groupId = request.paramAsLong(PARAM_GROUP_ID); - String projectUuid = request.param(PARAM_PROJECT_UUID); - String projectKey = request.param(PARAM_PROJECT_KEY); - - String groupName = searchGroupName(dbSession, groupNameParam, groupId); + public PermissionChange buildGroupPermissionChange(DbSession dbSession, PermissionRequest request) { + String groupName = searchGroupName(dbSession, request.groupName(), request.groupId()); PermissionChange permissionChange = new PermissionChange() - .setPermission(permission) + .setPermission(request.permission()) .setGroupName(groupName); - addProjectToPermissionChange(dbSession, permissionChange, projectUuid, projectKey); + addProjectToPermissionChange(dbSession, permissionChange, request); return permissionChange; } - private void addProjectToPermissionChange(DbSession dbSession, PermissionChange permissionChange, @Nullable String projectUuid, @Nullable String projectKey) { - if (isProjectUuidOrProjectKeyProvided(projectUuid, projectKey)) { - ComponentDto project = componentFinder.getProjectByUuidOrKey(dbSession, projectUuid, projectKey); + private void addProjectToPermissionChange(DbSession dbSession, PermissionChange permissionChange, PermissionRequest request) { + if (request.hasProject()) { + ComponentDto project = componentFinder.getProjectByUuidOrKey(dbSession, request.projectUuid(), request.projectKey()); permissionChange.setComponentKey(project.key()); } } - private static void checkParameters(@Nullable String groupName, @Nullable Long groupId) { - if (groupName != null ^ groupId != null) { - return; + Optional searchProject(PermissionRequest request) { + if (!request.hasProject()) { + return Optional.absent(); } - throw new BadRequestException("Group name or group id must be provided, not both"); - } - - static boolean isProjectUuidOrProjectKeyProvided(@Nullable String projectUuid, @Nullable String projectKey) { - return projectUuid != null || projectKey != null; - } - - Optional searchProject(Request request) { - String projectUuid = request.param(PARAM_PROJECT_UUID); - String projectKey = request.param(PARAM_PROJECT_KEY); - DbSession dbSession = dbClient.openSession(false); try { - if (isProjectUuidOrProjectKeyProvided(projectUuid, projectKey)) { - return Optional.of(componentFinder.getProjectByUuidOrKey(dbSession, projectUuid, projectKey)); - } - return Optional.absent(); + return Optional.of(componentFinder.getProjectByUuidOrKey(dbSession, request.projectUuid(), request.projectKey())); } finally { dbClient.closeSession(dbSession); } @@ -156,4 +137,42 @@ public class PermissionWsCommons { boolean projectPresentAndAdminPermissionsOnIt(Optional project) { return project.isPresent() && userSession.hasProjectPermissionByUuid(UserRole.ADMIN, project.get().projectUuid()); } + + static void createPermissionParameter(NewAction action) { + action.createParam(PARAM_PERMISSION) + .setDescription(PERMISSION_PARAM_DESCRIPTION) + .setRequired(true) + .setPossibleValues(POSSIBLE_PERMISSIONS); + } + + static void createGroupNameParameter(NewAction action) { + action.createParam(PARAM_GROUP_NAME) + .setDescription("Group name or 'anyone' (case insensitive)") + .setExampleValue("sonar-administrators"); + } + + static void createGroupIdParameter(NewAction action) { + action.createParam(PARAM_GROUP_ID) + .setDescription("Group id") + .setExampleValue("42"); + } + + static void createProjectUuidParameter(NewAction action) { + action.createParam(PARAM_PROJECT_UUID) + .setDescription("Project id") + .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); + } + + static void createProjectKeyParameter(NewAction action) { + action.createParam(PARAM_PROJECT_KEY) + .setDescription("Project key") + .setExampleValue("org.apache.hbas:hbase"); + } + + static void createUserLoginParameter(NewAction action) { + action.createParam(PARAM_USER_LOGIN) + .setRequired(true) + .setDescription("User login") + .setExampleValue("g.hopper"); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java index d375200ed1a..0df209ca6ba 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveGroupAction.java @@ -23,17 +23,17 @@ package org.sonar.server.permission.ws; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; +import org.sonar.server.permission.ws.PermissionRequest.Builder; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_ID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_NAME; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionWsCommons.createGroupIdParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createGroupNameParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; public class RemoveGroupAction implements PermissionsWsAction { @@ -54,38 +54,25 @@ public class RemoveGroupAction implements PermissionsWsAction { WebService.NewAction action = context.createAction(ACTION) .setDescription("Remove permission from a group.
" + "The group id or group name must be provided, not both.
" + + "If the project id or project key is provided, a project permission is removed.
" + "Requires 'Administer System' permission.") .setSince("5.2") .setPost(true) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setDescription("Permission") - .setRequired(true) - .setPossibleValues(GlobalPermissions.ALL); - - action.createParam(PARAM_GROUP_NAME) - .setDescription("Group name or 'anyone' (whatever the case)") - .setExampleValue("sonar-administrators"); - - action.createParam(PARAM_GROUP_ID) - .setDescription("Group id") - .setExampleValue("42"); - - action.createParam(PARAM_PROJECT_UUID) - .setDescription("Project id") - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); - - action.createParam(PARAM_PROJECT_KEY) - .setDescription("Project key") - .setExampleValue("org.apache.hbas:hbase"); + createPermissionParameter(action); + createGroupNameParameter(action); + createGroupIdParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request request, Response response) throws Exception { DbSession dbSession = dbClient.openSession(false); try { - PermissionChange permissionChange = permissionWsCommons.buildGroupPermissionChange(dbSession, request); + PermissionRequest permissionRequest = new Builder(request).withGroup().build(); + PermissionChange permissionChange = permissionWsCommons.buildGroupPermissionChange(dbSession, permissionRequest); permissionUpdater.removePermission(permissionChange); } finally { dbClient.closeSession(dbSession); diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java index f3592876d3e..ae94c3b133b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/RemoveUserAction.java @@ -23,23 +23,27 @@ package org.sonar.server.permission.ws; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; -import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; import org.sonar.server.permission.PermissionChange; import org.sonar.server.permission.PermissionUpdater; +import org.sonar.server.permission.ws.PermissionRequest.Builder; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_USER_LOGIN; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createUserLoginParameter; public class RemoveUserAction implements PermissionsWsAction { public static final String ACTION = "remove_user"; + private final DbClient dbClient; private final PermissionUpdater permissionUpdater; private final PermissionWsCommons permissionWsCommons; - public RemoveUserAction(PermissionUpdater permissionUpdater, PermissionWsCommons permissionWsCommons) { + public RemoveUserAction(DbClient dbClient, PermissionUpdater permissionUpdater, PermissionWsCommons permissionWsCommons) { + this.dbClient = dbClient; this.permissionUpdater = permissionUpdater; this.permissionWsCommons = permissionWsCommons; } @@ -48,36 +52,29 @@ public class RemoveUserAction implements PermissionsWsAction { public void define(WebService.NewController context) { WebService.NewAction action = context.createAction(ACTION) .setDescription("Remove permission from a user.
" + - "If the project id is provided, a project permission is removed.
" + + "If the project id or project key is provided, a project permission is removed.
" + "Requires 'Administer System' permission.") .setSince("5.2") .setPost(true) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setDescription("Permission") - .setRequired(true) - .setPossibleValues(GlobalPermissions.ALL); - - action.createParam(PARAM_USER_LOGIN) - .setRequired(true) - .setDescription("User login") - .setExampleValue("g.hopper"); - - action.createParam(PARAM_PROJECT_UUID) - .setDescription("Project id") - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d"); - - action.createParam(PARAM_PROJECT_KEY) - .setDescription("Project key") - .setExampleValue("org.apache.hbas:hbase"); + createPermissionParameter(action); + createUserLoginParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request request, Response response) throws Exception { - PermissionChange permissionChange = permissionWsCommons.buildUserPermissionChange(request); - permissionUpdater.removePermission(permissionChange); + DbSession dbSession = dbClient.openSession(false); + try { + PermissionRequest permissionRequest = new Builder(request).withUser().build(); + PermissionChange permissionChange = permissionWsCommons.buildUserPermissionChange(dbSession, permissionRequest); + permissionUpdater.removePermission(permissionChange); - response.noContent(); + response.noContent(); + } finally { + dbClient.closeSession(dbSession); + } } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java index 05d0f9783aa..329e12e6129 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/permission/ws/UsersAction.java @@ -27,32 +27,29 @@ import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.server.ws.WebService.SelectionMode; -import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.permission.UserWithPermission; import org.sonar.db.component.ComponentDto; import org.sonar.db.permission.PermissionQuery; import org.sonar.server.permission.PermissionFinder; import org.sonar.server.permission.UserWithPermissionQueryResult; -import org.sonar.server.user.UserSession; +import org.sonar.server.permission.ws.PermissionRequest.Builder; import org.sonarqube.ws.Common; import org.sonarqube.ws.Permissions.UsersResponse; import static com.google.common.base.Objects.firstNonNull; import static org.sonar.server.permission.PermissionQueryParser.toMembership; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; +import static org.sonar.server.permission.ws.PermissionWsCommons.createPermissionParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectKeyParameter; +import static org.sonar.server.permission.ws.PermissionWsCommons.createProjectUuidParameter; import static org.sonar.server.ws.WsUtils.writeProtobuf; public class UsersAction implements PermissionsWsAction { - private final UserSession userSession; private final PermissionFinder permissionFinder; private final PermissionWsCommons permissionWsCommons; - public UsersAction(UserSession userSession, PermissionFinder permissionFinder, PermissionWsCommons permissionWsCommons) { + public UsersAction(PermissionFinder permissionFinder, PermissionWsCommons permissionWsCommons) { this.permissionWsCommons = permissionWsCommons; - this.userSession = userSession; this.permissionFinder = permissionFinder; } @@ -71,29 +68,18 @@ public class UsersAction implements PermissionsWsAction { .setResponseExample(getClass().getResource("users-example.json")) .setHandler(this); - action.createParam(PARAM_PERMISSION) - .setExampleValue("scan") - .setRequired(true) - .setPossibleValues(GlobalPermissions.ALL); - - action.createParam(PARAM_PROJECT_UUID) - .setExampleValue("ce4c03d6-430f-40a9-b777-ad877c00aa4d") - .setDescription("Project id"); - - action.createParam(PARAM_PROJECT_KEY) - .setExampleValue("org.apache.hbas:hbase") - .setDescription("Project key"); + createPermissionParameter(action); + createProjectUuidParameter(action); + createProjectKeyParameter(action); } @Override public void handle(Request wsRequest, Response wsResponse) throws Exception { - int page = wsRequest.mandatoryParamAsInt(Param.PAGE); - int pageSize = wsRequest.mandatoryParamAsInt(Param.PAGE_SIZE); - - Optional project = permissionWsCommons.searchProject(wsRequest); + PermissionRequest request = new Builder(wsRequest).withPagination().build(); + Optional project = permissionWsCommons.searchProject(request); permissionWsCommons.checkPermissions(project); - PermissionQuery permissionQuery = buildPermissionQuery(wsRequest, project); - UsersResponse usersResponse = usersResponse(permissionQuery, page, pageSize); + PermissionQuery permissionQuery = buildPermissionQuery(request, project); + UsersResponse usersResponse = usersResponse(permissionQuery, request.page(), request.pageSize()); writeProtobuf(usersResponse, wsRequest, wsResponse); } @@ -124,24 +110,13 @@ public class UsersAction implements PermissionsWsAction { return userResponse.build(); } - private static PermissionQuery buildPermissionQuery(Request request, Optional project) { - String permission = request.mandatoryParam(PARAM_PERMISSION); - String selected = request.param(Param.SELECTED); - int page = request.mandatoryParamAsInt(Param.PAGE); - int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); - String query = request.param(Param.TEXT_QUERY); - if (query != null) { - selected = SelectionMode.ALL.value(); - } - + private static PermissionQuery buildPermissionQuery(PermissionRequest request, Optional project) { PermissionQuery.Builder permissionQuery = PermissionQuery.builder() - .permission(permission) - .pageIndex(page) - .pageSize(pageSize) - .membership(toMembership(firstNonNull(selected, SelectionMode.SELECTED.value()))); - if (query != null) { - permissionQuery.search(query); - } + .permission(request.permission()) + .pageIndex(request.page()) + .pageSize(request.pageSize()) + .membership(toMembership(firstNonNull(request.selected(), SelectionMode.SELECTED.value()))) + .search(request.query()); if (project.isPresent()) { permissionQuery.component(project.get().getKey()); } 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 a075735b391..707cbbde6c5 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 @@ -27,6 +27,7 @@ import org.sonar.api.server.ws.Request; 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.plugins.MimeTypes; public class WsUtils { @@ -51,4 +52,13 @@ public class WsUtils { IOUtils.closeQuietly(output); } } + + /** + * @throws BadRequestException + */ + public static void checkRequest(boolean expression, String errorMessage) { + if (!expression) { + throw new BadRequestException(errorMessage); + } + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java index ddf3e2581d2..c1197b227b8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddGroupActionTest.java @@ -27,6 +27,7 @@ import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -46,12 +47,13 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.server.component.ComponentTesting.newProjectDto; import static org.sonar.server.permission.ws.AddGroupAction.ACTION; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_ID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_NAME; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.PermissionsWs.ENDPOINT; @Category(DbTests.class) @@ -107,7 +109,7 @@ public class AddGroupActionTest { @Test public void add_with_project_uuid() throws Exception { insertGroup("sonar-administrators"); - insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); commit(); newRequest() @@ -125,7 +127,7 @@ public class AddGroupActionTest { @Test public void add_with_project_key() throws Exception { insertGroup("sonar-administrators"); - insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); commit(); newRequest() @@ -145,7 +147,7 @@ public class AddGroupActionTest { expectedException.expect(NotFoundException.class); insertGroup("sonar-administrators"); - insertComponent(ComponentTesting.newProjectDto("project-uuid").setKey("project-key")); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); commit(); newRequest() @@ -155,12 +157,25 @@ public class AddGroupActionTest { .execute(); } + @Test + public void fail_if_project_permission_withou_project() throws Exception { + expectedException.expect(BadRequestException.class); + + insertGroup("sonar-administrators"); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .execute(); + } + @Test public void fail_if_component_uuid_is_not_a_project() throws Exception { expectedException.expect(BadRequestException.class); insertGroup("sonar-administrators"); - ComponentDto project = ComponentTesting.newProjectDto("project-uuid").setKey("project-key"); + ComponentDto project = newProjectDto("project-uuid").setKey("project-key"); insertComponent(project); insertComponent(ComponentTesting.newFileDto(project, "file-uuid")); commit(); @@ -201,6 +216,21 @@ public class AddGroupActionTest { .execute(); } + @Test + public void fail_when_project_uuid_and_project_key_are_provided() throws Exception { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private WsTester.TestRequest newRequest() { return ws.newPostRequest(ENDPOINT, ACTION); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserActionTest.java index feb0334deb0..0c2ccf7d68d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/AddUserActionTest.java @@ -27,6 +27,7 @@ import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -52,6 +53,7 @@ import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSIO import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_USER_LOGIN; +import static org.sonar.server.permission.ws.PermissionsWs.ENDPOINT; @Category(DbTests.class) public class AddUserActionTest { @@ -72,13 +74,13 @@ public class AddUserActionTest { dbClient = db.getDbClient(); dbSession = db.getSession(); ws = new WsTester(new PermissionsWs( - new AddUserAction(permissionUpdater, new PermissionWsCommons(dbClient, new ComponentFinder(dbClient), userSession)))); + new AddUserAction(dbClient, permissionUpdater, new PermissionWsCommons(dbClient, new ComponentFinder(dbClient), userSession)))); userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); } @Test public void call_permission_service_with_right_data() throws Exception { - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); @@ -94,7 +96,7 @@ public class AddUserActionTest { dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key")); commit(); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PROJECT_UUID, "project-uuid") .setParam(PermissionWsCommons.PARAM_PERMISSION, SYSTEM_ADMIN) @@ -110,7 +112,7 @@ public class AddUserActionTest { dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key")); commit(); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PROJECT_KEY, "project-key") .setParam(PermissionWsCommons.PARAM_PERMISSION, SYSTEM_ADMIN) @@ -125,20 +127,30 @@ public class AddUserActionTest { public void fail_when_project_uuid_is_unknown() throws Exception { expectedException.expect(NotFoundException.class); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PROJECT_UUID, "unknown-project-uuid") .setParam(PermissionWsCommons.PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); } + @Test + public void fail_when_project_permission_without_project() throws Exception { + expectedException.expect(BadRequestException.class); + + ws.newPostRequest(ENDPOINT, ACTION) + .setParam(PARAM_USER_LOGIN, "ray.bradbury") + .setParam(PermissionWsCommons.PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .execute(); + } + @Test public void fail_when_component_is_not_a_project() throws Exception { expectedException.expect(BadRequestException.class); insertComponent(newFileDto(newProjectDto("project-uuid"), "file-uuid")); commit(); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PROJECT_UUID, "file-uuid") .setParam(PermissionWsCommons.PARAM_PERMISSION, SYSTEM_ADMIN) @@ -149,7 +161,7 @@ public class AddUserActionTest { public void fail_when_get_request() throws Exception { expectedException.expect(ServerException.class); - ws.newGetRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newGetRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "george.orwell") .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); @@ -159,7 +171,7 @@ public class AddUserActionTest { public void fail_when_user_login_is_missing() throws Exception { expectedException.expect(IllegalArgumentException.class); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) .execute(); } @@ -168,11 +180,26 @@ public class AddUserActionTest { public void fail_when_permission_is_missing() throws Exception { expectedException.expect(IllegalArgumentException.class); - ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + ws.newPostRequest(ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "jrr.tolkien") .execute(); } + @Test + public void fail_when_project_uuid_and_project_key_are_provided() throws Exception { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); + commit(); + + ws.newPostRequest(ENDPOINT, ACTION) + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_USER_LOGIN, "ray.bradbury") + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private void insertComponent(ComponentDto component) { dbClient.componentDao().insert(dbSession, component); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java index 90e08c50a1e..b0be7661f96 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/GroupsActionTest.java @@ -38,6 +38,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.user.GroupDto; import org.sonar.db.user.GroupRoleDto; import org.sonar.server.component.ComponentFinder; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.permission.PermissionFinder; @@ -51,6 +52,7 @@ import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.server.component.ComponentTesting.newProjectDto; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.test.JsonAssert.assertJson; @@ -155,6 +157,15 @@ public class GroupsActionTest { .doesNotContain("group-3"); } + @Test + public void fail_if_project_permission_without_project() { + expectedException.expect(BadRequestException.class); + + ws.newRequest() + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .execute(); + } + @Test public void fail_if_not_logged_in() { expectedException.expect(UnauthorizedException.class); @@ -183,6 +194,19 @@ public class GroupsActionTest { .execute(); } + @Test + public void fail_if_project_uuid_and_project_key_are_provided() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key")); + + ws.newRequest() + .setParam(PARAM_PERMISSION, SCAN_EXECUTION) + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private GroupDto insertGroup(GroupDto group) { GroupDto result = dbClient.groupDao().insert(dbSession, group); commit(); 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 6d7b22b7aa1..ee80661ad6d 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 @@ -27,6 +27,7 @@ import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.component.ComponentDto; @@ -50,8 +51,8 @@ import static org.sonar.server.component.ComponentTesting.newProjectDto; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_ID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_GROUP_NAME; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; -import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.RemoveGroupAction.ACTION; @Category(DbTests.class) @@ -145,6 +146,16 @@ public class RemoveGroupActionTest { .execute(); } + @Test + public void fail_when_project_project_permission_without_project() throws Exception { + expectedException.expect(BadRequestException.class); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .execute(); + } + @Test public void fail_when_component_is_not_a_project() throws Exception { expectedException.expect(BadRequestException.class); @@ -197,6 +208,21 @@ public class RemoveGroupActionTest { .execute(); } + @Test + public void fail_when_project_uuid_and_project_key_are_provided() throws Exception { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); + commit(); + + newRequest() + .setParam(PARAM_GROUP_NAME, "sonar-administrators") + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private WsTester.TestRequest newRequest() { return ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserActionTest.java index 9fa33c0034b..296a0f45d7e 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/RemoveUserActionTest.java @@ -27,6 +27,7 @@ import org.junit.experimental.categories.Category; import org.junit.rules.ExpectedException; import org.mockito.ArgumentCaptor; import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -51,6 +52,7 @@ import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSIO import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_USER_LOGIN; +import static org.sonar.server.permission.ws.PermissionsWs.ENDPOINT; import static org.sonar.server.permission.ws.RemoveUserAction.ACTION; @Category(DbTests.class) @@ -72,7 +74,7 @@ public class RemoveUserActionTest { dbClient = db.getDbClient(); dbSession = db.getSession(); ws = new WsTester(new PermissionsWs( - new RemoveUserAction(permissionUpdater, new PermissionWsCommons(dbClient, new ComponentFinder(dbClient), userSession)))); + new RemoveUserAction(dbClient, permissionUpdater, new PermissionWsCommons(dbClient, new ComponentFinder(dbClient), userSession)))); userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); } @@ -126,7 +128,17 @@ public class RemoveUserActionTest { ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) .setParam(PARAM_USER_LOGIN, "ray.bradbury") .setParam(PARAM_PROJECT_UUID, "unknown-project-uuid") - .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .execute(); + } + + @Test + public void fail_when_project_permission_without_permission() throws Exception { + expectedException.expect(BadRequestException.class); + + ws.newPostRequest(PermissionsWs.ENDPOINT, ACTION) + .setParam(PARAM_USER_LOGIN, "ray.bradbury") + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) .execute(); } @@ -170,6 +182,20 @@ public class RemoveUserActionTest { .execute(); } + @Test + public void fail_when_project_uuid_and_project_key_are_provided() throws Exception { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + insertComponent(newProjectDto("project-uuid").setKey("project-key")); + + ws.newPostRequest(ENDPOINT, ACTION) + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_USER_LOGIN, "ray.bradbury") + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private void insertComponent(ComponentDto component) { dbClient.componentDao().insert(dbSession, component); dbSession.commit(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java index f3fc0c3ac03..84da264f01d 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/permission/ws/UsersActionTest.java @@ -28,6 +28,7 @@ import org.junit.rules.ExpectedException; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.server.ws.WebService.SelectionMode; import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; @@ -35,6 +36,7 @@ import org.sonar.db.component.ComponentDto; import org.sonar.db.user.UserDto; import org.sonar.db.user.UserRoleDto; import org.sonar.server.component.ComponentFinder; +import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.UnauthorizedException; import org.sonar.server.permission.PermissionFinder; @@ -43,10 +45,12 @@ import org.sonar.server.ws.WsActionTester; import org.sonar.test.DbTests; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.api.web.UserRole.ISSUE_ADMIN; import static org.sonar.core.permission.GlobalPermissions.SCAN_EXECUTION; import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; import static org.sonar.server.component.ComponentTesting.newProjectDto; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PERMISSION; +import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_KEY; import static org.sonar.server.permission.ws.PermissionWsCommons.PARAM_PROJECT_UUID; import static org.sonar.test.JsonAssert.assertJson; @@ -69,7 +73,7 @@ public class UsersActionTest { public void setUp() { PermissionFinder permissionFinder = new PermissionFinder(dbClient); PermissionWsCommons permissionWsCommons = new PermissionWsCommons(dbClient, new ComponentFinder(dbClient), userSession); - underTest = new UsersAction(userSession, permissionFinder, permissionWsCommons); + underTest = new UsersAction(permissionFinder, permissionWsCommons); ws = new WsActionTester(underTest); userSession.login("login").setGlobalPermissions(SYSTEM_ADMIN); @@ -109,12 +113,12 @@ public class UsersActionTest { dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key")); ComponentDto project = dbClient.componentDao().selectOrFailByUuid(dbSession, "project-uuid"); UserDto user = insertUser(new UserDto().setLogin("project-user-login").setName("project-user-name")); - insertUserRole(new UserRoleDto().setRole(SCAN_EXECUTION).setUserId(user.getId()).setResourceId(project.getId())); + insertUserRole(new UserRoleDto().setRole(ISSUE_ADMIN).setUserId(user.getId()).setResourceId(project.getId())); commit(); userSession.login().addProjectUuidPermissions(SYSTEM_ADMIN, "project-uuid"); String result = ws.newRequest() - .setParam(PARAM_PERMISSION, SCAN_EXECUTION) + .setParam(PARAM_PERMISSION, ISSUE_ADMIN) .setParam(PARAM_PROJECT_UUID, "project-uuid") .execute().getInput(); @@ -132,7 +136,6 @@ public class UsersActionTest { assertThat(result).contains("login-1") .doesNotContain("login-2") .doesNotContain("login-3"); - } @Test @@ -145,6 +148,16 @@ public class UsersActionTest { assertThat(result).contains("login-1", "login-2", "login-3"); } + @Test + public void fail_if_project_permission_without_project() { + expectedException.expect(BadRequestException.class); + + ws.newRequest() + .setParam(PARAM_PERMISSION, UserRole.ISSUE_ADMIN) + .setParam(Param.SELECTED, SelectionMode.ALL.value()) + .execute(); + } + @Test public void fail_if_permission_parameter_is_not_filled() { expectedException.expect(IllegalArgumentException.class); @@ -172,6 +185,20 @@ public class UsersActionTest { .execute(); } + @Test + public void fail_if_project_uuid_and_project_key_are_provided() { + expectedException.expect(BadRequestException.class); + expectedException.expectMessage("Project id or project key can be provided, not both."); + dbClient.componentDao().insert(dbSession, newProjectDto("project-uuid").setKey("project-key")); + commit(); + + ws.newRequest() + .setParam(PARAM_PERMISSION, SYSTEM_ADMIN) + .setParam(PARAM_PROJECT_UUID, "project-uuid") + .setParam(PARAM_PROJECT_KEY, "project-key") + .execute(); + } + private UserDto insertUser(UserDto userDto) { UserDto user = dbClient.userDao().insert(dbSession, userDto.setActive(true)); commit(); -- 2.39.5