diff options
author | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-10-12 18:53:31 +0200 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@sonarsource.com> | 2016-10-13 12:13:11 +0200 |
commit | 73b71c9e8eb47c6d833cd5f4725be50719598b88 (patch) | |
tree | f21ba43e4888cddbf49d3b58db607206fba1183d /server | |
parent | 8595a520f31a9f2b0ea77e10086685d2290ac1f3 (diff) | |
download | sonarqube-73b71c9e8eb47c6d833cd5f4725be50719598b88.tar.gz sonarqube-73b71c9e8eb47c6d833cd5f4725be50719598b88.zip |
Support organizations in user group web services
Diffstat (limited to 'server')
42 files changed, 1341 insertions, 941 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java index 6cd2552d378..5f486cb2edb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/GroupsAction.java @@ -94,22 +94,19 @@ public class GroupsAction implements UsersWsAction { .pageSize(pageSize) .build(); - DbSession session = dbClient.openSession(false); - try { - UserDto user = dbClient.userDao().selectByLogin(session, login); + try (DbSession dbSession = dbClient.openSession(false)) { + UserDto user = dbClient.userDao().selectByLogin(dbSession, login); if (user == null) { throw new NotFoundException(String.format("User with login '%s' has not been found", login)); } - int total = dbClient.groupMembershipDao().countGroups(session, query, user.getId()); + int total = dbClient.groupMembershipDao().countGroups(dbSession, query, user.getId()); Paging paging = forPageIndex(page).withPageSize(pageSize).andTotal(total); - List<GroupMembershipDto> groups = dbClient.groupMembershipDao().selectGroups(session, query, user.getId(), paging.offset(), pageSize); + List<GroupMembershipDto> groups = dbClient.groupMembershipDao().selectGroups(dbSession, query, user.getId(), paging.offset(), pageSize); JsonWriter json = response.newJsonWriter().beginObject(); writeGroups(json, groups); writePaging(json, paging); json.endObject().close(); - } finally { - session.close(); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/AddUserAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/AddUserAction.java index 5200b7e935e..041219b42b8 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/AddUserAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/AddUserAction.java @@ -19,7 +19,6 @@ */ package org.sonar.server.usergroups.ws; -import java.util.Arrays; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewAction; @@ -27,30 +26,28 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; import org.sonar.db.user.UserGroupDto; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.user.UserSession; import static java.lang.String.format; -import static org.sonar.db.MyBatis.closeQuietly; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_ID; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_LOGIN; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.createGroupParameters; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.createLoginParameter; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_LOGIN; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineGroupWsParameters; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineLoginWsParameter; public class AddUserAction implements UserGroupsWsAction { private final DbClient dbClient; - private final UserGroupFinder userGroupFinder; private final UserSession userSession; + private final GroupWsSupport support; - public AddUserAction(DbClient dbClient, UserGroupFinder userGroupFinder, UserSession userSession) { + public AddUserAction(DbClient dbClient, UserSession userSession, GroupWsSupport support) { this.dbClient = dbClient; - this.userGroupFinder = userGroupFinder; this.userSession = userSession; + this.support = support; } @Override @@ -62,40 +59,34 @@ public class AddUserAction implements UserGroupsWsAction { .setPost(true) .setSince("5.2"); - createGroupParameters(action); - createLoginParameter(action); + defineGroupWsParameters(action); + defineLoginWsParameter(action); } @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - WsGroupRef wsGroupRef = WsGroupRef.newWsGroupRefFromUserGroupRequest(request); - String login = request.mandatoryParam(PARAM_LOGIN); - - DbSession dbSession = dbClient.openSession(false); - try { - GroupDto group = userGroupFinder.getGroup(dbSession, wsGroupRef); + try (DbSession dbSession = dbClient.openSession(false)) { + GroupId groupId = support.findGroup(dbSession, request); + String login = request.mandatoryParam(PARAM_LOGIN); UserDto user = dbClient.userDao().selectActiveUserByLogin(dbSession, login); if (user == null) { throw new NotFoundException(format("Could not find a user with login '%s'", login)); } - if (userIsNotYetMemberOf(dbSession, login, group)) { - UserGroupDto userGroup = new UserGroupDto().setGroupId(group.getId()).setUserId(user.getId()); - dbClient.userGroupDao().insert(dbSession, userGroup); + if (userIsNotYetMemberOf(dbSession, user.getId(), groupId)) { + UserGroupDto membershipDto = new UserGroupDto().setGroupId(groupId.getId()).setUserId(user.getId()); + dbClient.userGroupDao().insert(dbSession, membershipDto); dbSession.commit(); } response.noContent(); - } finally { - closeQuietly(dbSession); } - } - private boolean userIsNotYetMemberOf(DbSession dbSession, String login, GroupDto group) { - return !dbClient.groupMembershipDao().selectGroupsByLogins(dbSession, Arrays.asList(login)).get(login).contains(group.getName()); + private boolean userIsNotYetMemberOf(DbSession dbSession, long userId, GroupId groupId) { + return !dbClient.groupMembershipDao().selectGroupIdsByUserId(dbSession, userId).contains(groupId.getId()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java index a043e4f73dc..f1884d31e12 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/CreateAction.java @@ -23,47 +23,56 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.server.ws.WebService.NewController; -import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.user.UserGroupValidation; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.GroupDto; import org.sonar.server.user.UserSession; +import org.sonarqube.ws.WsUserGroups; import static org.sonar.api.user.UserGroupValidation.GROUP_NAME_MAX_LENGTH; -import static org.sonar.db.MyBatis.closeQuietly; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.DESCRIPTION_MAX_LENGTH; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.PARAM_DESCRIPTION; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.PARAM_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.DESCRIPTION_MAX_LENGTH; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_DESCRIPTION; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY; +import static org.sonar.server.usergroups.ws.GroupWsSupport.toProtobuf; +import static org.sonar.server.ws.WsUtils.writeProtobuf; public class CreateAction implements UserGroupsWsAction { private final DbClient dbClient; private final UserSession userSession; - private final UserGroupUpdater groupUpdater; + private final GroupWsSupport support; - public CreateAction(DbClient dbClient, UserSession userSession, UserGroupUpdater groupUpdater) { + public CreateAction(DbClient dbClient, UserSession userSession, GroupWsSupport support) { this.dbClient = dbClient; - this.groupUpdater = groupUpdater; this.userSession = userSession; + this.support = support; } @Override - public void define(NewController context) { - NewAction action = context.createAction("create") + public void define(NewController controller) { + NewAction action = controller.createAction("create") .setDescription("Create a group.") .setHandler(this) .setPost(true) .setResponseExample(getClass().getResource("example-create.json")) .setSince("5.2"); - action.createParam(PARAM_NAME) + action.createParam(PARAM_ORGANIZATION_KEY) + .setDescription("Key of organization. If unset then default organization is used.") + .setExampleValue("my-org") + .setSince("6.2"); + + action.createParam(PARAM_GROUP_NAME) .setDescription(String.format("Name for the new group. A group name cannot be larger than %d characters and must be unique. " + "The value 'anyone' (whatever the case) is reserved and cannot be used.", GROUP_NAME_MAX_LENGTH)) .setExampleValue("sonar-users") .setRequired(true); - action.createParam(PARAM_DESCRIPTION) + action.createParam(PARAM_GROUP_DESCRIPTION) .setDescription(String.format("Description for the new group. A group description cannot be larger than %d characters.", DESCRIPTION_MAX_LENGTH)) .setExampleValue("Default group for new users"); } @@ -72,25 +81,28 @@ public class CreateAction implements UserGroupsWsAction { public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - String name = request.mandatoryParam(PARAM_NAME); - String description = request.param(PARAM_DESCRIPTION); + try (DbSession dbSession = dbClient.openSession(false)) { + OrganizationDto organization = support.findOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION_KEY)); + GroupDto group = new GroupDto() + .setOrganizationUuid(organization.getUuid()) + .setName(request.mandatoryParam(PARAM_GROUP_NAME)) + .setDescription(request.param(PARAM_GROUP_DESCRIPTION)); - groupUpdater.validateName(name); - if (description != null) { - groupUpdater.validateDescription(description); - } + // validations + UserGroupValidation.validateGroupName(group.getName()); + support.validateDescription(group.getDescription()); + support.checkNameDoesNotExist(dbSession, group.getOrganizationUuid(), group.getName()); - DbSession session = dbClient.openSession(false); - try { - groupUpdater.checkNameIsUnique(name, session); - GroupDto newGroup = dbClient.groupDao().insert(session, new GroupDto().setName(name).setDescription(description)); - session.commit(); + dbClient.groupDao().insert(dbSession, group); + dbSession.commit(); - JsonWriter json = response.newJsonWriter().beginObject(); - groupUpdater.writeGroup(json, newGroup, 0); - json.endObject().close(); - } finally { - closeQuietly(session); + writeResponse(request, response, organization, group); } } + + private void writeResponse(Request request, Response response, OrganizationDto organization, GroupDto group) { + WsUserGroups.CreateResponse.Builder respBuilder = WsUserGroups.CreateResponse.newBuilder(); + respBuilder.setGroup(toProtobuf(organization, group, 0)); + writeProtobuf(respBuilder.build(), request, response); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java index 829edb3a892..48c390a11d2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/DeleteAction.java @@ -19,6 +19,7 @@ */ package org.sonar.server.usergroups.ws; +import java.util.Optional; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; import org.sonar.api.server.ws.Request; @@ -28,28 +29,32 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; import org.sonar.db.permission.PermissionQuery; import org.sonar.db.user.GroupDto; +import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.user.UserSession; import static com.google.common.base.Preconditions.checkArgument; import static java.lang.String.format; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_ID; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineGroupWsParameters; public class DeleteAction implements UserGroupsWsAction { private final DbClient dbClient; - private final UserGroupFinder userGroupFinder; private final UserSession userSession; + private final GroupWsSupport support; private final Settings settings; + private final DefaultOrganizationProvider defaultOrganizationProvider; - public DeleteAction(DbClient dbClient, UserGroupFinder userGroupFinder, UserSession userSession, Settings settings) { + public DeleteAction(DbClient dbClient, UserSession userSession, GroupWsSupport support, Settings settings, + DefaultOrganizationProvider defaultOrganizationProvider) { this.dbClient = dbClient; - this.userGroupFinder = userGroupFinder; this.userSession = userSession; + this.support = support; this.settings = settings; + this.defaultOrganizationProvider = defaultOrganizationProvider; } @Override @@ -63,62 +68,65 @@ public class DeleteAction implements UserGroupsWsAction { .setSince("5.2") .setPost(true); - UserGroupsWsParameters.createGroupParameters(action); + defineGroupWsParameters(action); } @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - WsGroupRef groupRef = WsGroupRef.newWsGroupRefFromUserGroupRequest(request); - - DbSession dbSession = dbClient.openSession(false); - try { - GroupDto group = userGroupFinder.getGroup(dbSession, groupRef); - long groupId = group.getId(); + try (DbSession dbSession = dbClient.openSession(false)) { + GroupId groupId = support.findGroup(dbSession, request); checkNotTryingToDeleteDefaultGroup(dbSession, groupId); - checkNotTryingToDeleteLastSystemAdminGroup(dbSession, group.getName()); + checkNotTryingToDeleteLastSystemAdminGroup(dbSession, groupId); removeGroupMembers(dbSession, groupId); removeGroupPermissions(dbSession, groupId); removeFromPermissionTemplates(dbSession, groupId); - dbClient.groupDao().deleteById(dbSession, groupId); + dbClient.groupDao().deleteById(dbSession, groupId.getId()); dbSession.commit(); response.noContent(); - } finally { - MyBatis.closeQuietly(dbSession); } } - private void checkNotTryingToDeleteDefaultGroup(DbSession dbSession, long groupId) { + /** + * The property "default group" is used when registering a new user so that + * he automatically becomes a member of this group. This feature does not + * not exist on non-default organizations yet as organization settings + * are not implemented. + */ + private void checkNotTryingToDeleteDefaultGroup(DbSession dbSession, GroupId group) { String defaultGroupName = settings.getString(CoreProperties.CORE_DEFAULT_GROUP); - GroupDto defaultGroup = dbClient.groupDao().selectOrFailByName(dbSession, defaultGroupName); - checkArgument(groupId != defaultGroup.getId(), - format("Default group '%s' cannot be deleted", defaultGroupName)); + if (defaultGroupName != null && group.getOrganizationUuid().equals(defaultOrganizationProvider.get().getUuid())) { + Optional<GroupDto> defaultGroup = dbClient.groupDao().selectByName(dbSession, group.getOrganizationUuid(), defaultGroupName); + checkArgument(!defaultGroup.isPresent() || defaultGroup.get().getId() != group.getId(), + format("Default group '%s' cannot be deleted", defaultGroupName)); + } } - private void checkNotTryingToDeleteLastSystemAdminGroup(DbSession dbSession, String groupName) { - boolean hasAdminPermission = dbClient.roleDao() - .selectGroupPermissions(dbSession, groupName, null) + private void checkNotTryingToDeleteLastSystemAdminGroup(DbSession dbSession, GroupId group) { + boolean hasAdminPermission = dbClient.groupPermissionDao() + .selectGroupPermissions(dbSession, group.getId(), null) .contains(GlobalPermissions.SYSTEM_ADMIN); + // TODO support organizations boolean isOneRemainingAdminGroup = dbClient.groupPermissionDao().countGroups(dbSession, GlobalPermissions.SYSTEM_ADMIN, null) == 1; boolean hasNoStandaloneAdminUser = dbClient.userPermissionDao().countUsers(dbSession, PermissionQuery.builder().setPermission(GlobalPermissions.SYSTEM_ADMIN).withAtLeastOnePermission().build()) == 0; boolean isLastAdminGroup = hasAdminPermission && isOneRemainingAdminGroup && hasNoStandaloneAdminUser; - checkArgument(!isLastAdminGroup, "The last system admin group '%s' cannot be deleted", groupName); + checkArgument(!isLastAdminGroup, "The last system admin group cannot be deleted"); } - private void removeGroupMembers(DbSession dbSession, long groupId) { - dbClient.userGroupDao().deleteMembersByGroupId(dbSession, groupId); + private void removeGroupMembers(DbSession dbSession, GroupId groupId) { + dbClient.userGroupDao().deleteByGroupId(dbSession, groupId.getId()); } - private void removeGroupPermissions(DbSession dbSession, long groupId) { - dbClient.roleDao().deleteGroupRolesByGroupId(dbSession, groupId); + private void removeGroupPermissions(DbSession dbSession, GroupId groupId) { + dbClient.roleDao().deleteGroupRolesByGroupId(dbSession, groupId.getId()); } - private void removeFromPermissionTemplates(DbSession dbSession, long groupId) { - dbClient.permissionTemplateDao().deleteByGroup(dbSession, groupId); + private void removeFromPermissionTemplates(DbSession dbSession, GroupId groupId) { + dbClient.permissionTemplateDao().deleteByGroup(dbSession, groupId.getId()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupFinder.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupId.java index 38b3cc3d94d..d9b4544a0ee 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupFinder.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupId.java @@ -19,35 +19,38 @@ */ package org.sonar.server.usergroups.ws; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; +import javax.annotation.concurrent.Immutable; import org.sonar.db.user.GroupDto; -import static org.sonar.server.ws.WsUtils.checkFound; +import static java.util.Objects.requireNonNull; -public class UserGroupFinder { - private final DbClient dbClient; - - public UserGroupFinder(DbClient dbClient) { - this.dbClient = dbClient; - } +/** + * Reference to a user group, as used internally by the backend. It does + * not support reference to virtual groups "anyone". + * + * @see GroupWsRef + * @see GroupIdOrAnyone + */ +@Immutable +public class GroupId { - public GroupDto getGroup(DbSession dbSession, WsGroupRef group) { - Long groupId = group.id(); - String groupName = group.name(); + private final long id; + private final String organizationUuid; - GroupDto groupDto = null; + public GroupId(String organizationUuid, long id) { + this.id = id; + this.organizationUuid = requireNonNull(organizationUuid); + } - if (groupId != null) { - groupDto = checkFound(dbClient.groupDao().selectById(dbSession, groupId), - "Group with id '%d' is not found", groupId); - } + public long getId() { + return id; + } - if (groupName != null) { - groupDto = checkFound(dbClient.groupDao().selectByName(dbSession, groupName), - "Group with name '%s' is not found", groupName); - } + public String getOrganizationUuid() { + return organizationUuid; + } - return groupDto; + public static GroupId from(GroupDto dto) { + return new GroupId(dto.getOrganizationUuid(), dto.getId()); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupIdOrAnyone.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupIdOrAnyone.java new file mode 100644 index 00000000000..ae782630882 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupIdOrAnyone.java @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.usergroups.ws; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.db.user.GroupDto; + +import static java.util.Objects.requireNonNull; + +/** + * Reference to a user group, as used internally by the backend. Contrary to + * {@link GroupId}, it supports reference to virtual groups "anyone". In these + * cases {@link #getId()} returns {@code null} + * + * @see GroupWsRef + * @see GroupId + */ +@Immutable +public class GroupIdOrAnyone { + + private final Long id; + private final String organizationUuid; + + public GroupIdOrAnyone(String organizationUuid, @Nullable Long id) { + this.id = id; + this.organizationUuid = requireNonNull(organizationUuid); + } + + public GroupIdOrAnyone(GroupDto group) { + this.id = requireNonNull(group.getId()); + this.organizationUuid = requireNonNull(group.getOrganizationUuid()); + } + + public boolean isAnyone() { + return id == null; + } + + @CheckForNull + public Long getId() { + return id; + } + + public String getOrganizationUuid() { + return organizationUuid; + } + + public static GroupIdOrAnyone from(GroupDto dto) { + return new GroupIdOrAnyone(dto.getOrganizationUuid(), dto.getId()); + } + + public static GroupIdOrAnyone forAnyone(String organizationUuid) { + return new GroupIdOrAnyone(organizationUuid, null); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsRef.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsRef.java new file mode 100644 index 00000000000..db97f15b15c --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsRef.java @@ -0,0 +1,163 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.usergroups.ws; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import javax.annotation.concurrent.Immutable; +import org.sonar.api.security.DefaultGroups; + +import static com.google.common.base.Preconditions.checkArgument; +import static com.google.common.base.Preconditions.checkState; +import static java.util.Objects.requireNonNull; +import static org.sonar.server.ws.WsUtils.checkRequest; + +/** + * Reference to a user group <b>as declared by web service requests</b>. It is one, and only one, + * of these two options: + * <ul> + * <li>group id, for instance 1234</li> + * <li>group name and optional organization key</li> + * </ul> + * + * The reference is then converted to a {@link GroupId} or {@link GroupIdOrAnyone}. + */ +@Immutable +public class GroupWsRef { + + private static final int NULL_ID = -1; + + private final long id; + private final String organizationKey; + private final String name; + + private GroupWsRef(long id, @Nullable String organizationKey, @Nullable String name) { + this.id = id; + this.organizationKey = organizationKey; + this.name = name; + } + + /** + * @return {@code true} if id is defined and {@link #getId()} can be called. If {@code false}, then + * the couple {organizationKey, name} is defined and the methods {@link #getOrganizationKey()}/{@link #getName()} + * can be called. + */ + public boolean hasId() { + return id != NULL_ID; + } + + /** + * @return the group id + * @throws IllegalStateException if {@link #getId()} is {@code false} + */ + public long getId() { + checkState(hasId(), "Id is not present. Please see hasId()."); + return id; + } + + /** + * @return the organization key + * @throws IllegalStateException if {@link #getId()} is {@code true} + */ + @CheckForNull + public String getOrganizationKey() { + checkState(!hasId(), "Organization is not present. Please see hasId()."); + return organizationKey; + } + + /** + * @return the non-null group name. Can be anyone. + * @throws IllegalStateException if {@link #getId()} is {@code true} + */ + public String getName() { + checkState(!hasId(), "Name is not present. Please see hasId()."); + return name; + } + + /** + * Creates a reference to a group by its id. Virtual groups "Anyone" can't be returned + * as they can't be referenced by an id. + */ + static GroupWsRef fromId(long id) { + checkArgument(id > -1, "Group id must be positive: %s", id); + return new GroupWsRef(id, null, null); + } + + /** + * Creates a reference to a group by its organization and name. Virtual groups "Anyone" are + * supported. + * + * @param organizationKey key of organization. If {@code null}, then default organization will be used. + * @param name non-null name. Can refer to anyone group (case-insensitive {@code "anyone"}). + */ + static GroupWsRef fromName(@Nullable String organizationKey, String name) { + return new GroupWsRef(NULL_ID, organizationKey, requireNonNull(name)); + } + + public static GroupWsRef create(@Nullable Long id, @Nullable String organizationKey, @Nullable String name) { + if (id != null) { + checkRequest(organizationKey == null && name == null, "Either group id or couple organization/group name must be set"); + return fromId(id); + } + + checkRequest(name != null, "Group name or group id must be provided"); + return fromName(organizationKey, name); + } + + public boolean isAnyone() { + return !hasId() && DefaultGroups.isAnyone(name); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + GroupWsRef groupRef = (GroupWsRef) o; + if (id != groupRef.id) { + return false; + } + if (organizationKey != null ? !organizationKey.equals(groupRef.organizationKey) : (groupRef.organizationKey != null)) { + return false; + } + return name != null ? name.equals(groupRef.name) : (groupRef.name == null); + } + + @Override + public int hashCode() { + int result = (int) (id ^ (id >>> 32)); + result = 31 * result + (organizationKey != null ? organizationKey.hashCode() : 0); + result = 31 * result + (name != null ? name.hashCode() : 0); + return result; + } + + @Override + public String toString() { + StringBuilder sb = new StringBuilder("GroupWsRef{"); + sb.append("id=").append(id); + sb.append(", organizationKey='").append(organizationKey).append('\''); + sb.append(", name='").append(name).append('\''); + sb.append('}'); + return sb.toString(); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsSupport.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsSupport.java new file mode 100644 index 00000000000..d702b684ade --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/GroupWsSupport.java @@ -0,0 +1,195 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.usergroups.ws; + +import java.util.Optional; +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.user.UserGroupValidation; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.user.GroupDto; +import org.sonar.server.exceptions.BadRequestException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.DefaultOrganizationProvider; +import org.sonarqube.ws.WsUserGroups; + +import static com.google.common.base.Preconditions.checkArgument; +import static java.lang.String.format; +import static org.sonar.server.ws.WsUtils.checkFound; +import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; + +/** + * Factorizes code about user groups between web services + */ +public class GroupWsSupport { + + static final String PARAM_GROUP_ID = "id"; + static final String PARAM_ORGANIZATION_KEY = "organization"; + static final String PARAM_GROUP_NAME = "name"; + static final String PARAM_GROUP_DESCRIPTION = "description"; + static final String PARAM_LOGIN = "login"; + + // Database column size should be 500 (since migration #353), + // but on some instances, column size is still 200, + // hence the validation is done with 200 + static final int DESCRIPTION_MAX_LENGTH = 200; + + private final DbClient dbClient; + private final DefaultOrganizationProvider defaultOrganizationProvider; + + public GroupWsSupport(DbClient dbClient, DefaultOrganizationProvider defaultOrganizationProvider) { + this.dbClient = dbClient; + this.defaultOrganizationProvider = defaultOrganizationProvider; + } + + /** + * Find a group by its id (parameter {@link #PARAM_GROUP_ID}) or couple organization key/group name + * (parameters {@link #PARAM_ORGANIZATION_KEY} and {@link #PARAM_GROUP_NAME}). The virtual + * group "Anyone" is not supported. + * + * @throws NotFoundException if parameters are missing/incorrect, if the requested group does not exist + * or if the virtual group "Anyone" is requested. + */ + public GroupId findGroup(DbSession dbSession, Request request) { + Long id = request.paramAsLong(PARAM_GROUP_ID); + String organizationKey = request.param(PARAM_ORGANIZATION_KEY); + String name = request.param(PARAM_GROUP_NAME); + return findGroup(dbSession, GroupWsRef.create(id, organizationKey, name)); + } + + /** + * Finds a user group by its reference. If organization is not defined then group + * is searched in default organization. + * + * @return non-null group + * @throws NotFoundException if the requested group does not exist + * @throws NotFoundException if the requested group is Anyone + */ + public GroupId findGroup(DbSession dbSession, GroupWsRef ref) { + if (ref.hasId()) { + GroupDto group = dbClient.groupDao().selectById(dbSession, ref.getId()); + checkFound(group, "No group with id '%s'", ref.getId()); + return GroupId.from(group); + } + + OrganizationDto org = findOrganizationByKey(dbSession, ref.getOrganizationKey()); + Optional<GroupDto> group = dbClient.groupDao().selectByName(dbSession, org.getUuid(), ref.getName()); + checkFoundWithOptional(group, "No group with name '%s' in organization '%s'", ref.getName(), org.getKey()); + return GroupId.from(group.get()); + } + + public GroupIdOrAnyone findGroupOrAnyone(DbSession dbSession, GroupWsRef ref) { + if (ref.hasId()) { + GroupDto group = dbClient.groupDao().selectById(dbSession, ref.getId()); + checkFound(group, "No group with id '%s'", ref.getId()); + return GroupIdOrAnyone.from(group); + } + + OrganizationDto org = findOrganizationByKey(dbSession, ref.getOrganizationKey()); + if (ref.isAnyone()) { + return GroupIdOrAnyone.forAnyone(org.getUuid()); + } + + Optional<GroupDto> group = dbClient.groupDao().selectByName(dbSession, org.getUuid(), ref.getName()); + checkFoundWithOptional(group, "No group with name '%s' in organization '%s'", ref.getName(), org.getKey()); + return GroupIdOrAnyone.from(group.get()); + } + + /** + * Loads organization from database by its key. + * @param dbSession + * @param key the organization key, or {@code null} to get the default organization + * @return non-null organization + * @throws NotFoundException if no organizations match the provided key + */ + public OrganizationDto findOrganizationByKey(DbSession dbSession, @Nullable String key) { + String effectiveKey = key; + if (effectiveKey == null) { + effectiveKey = defaultOrganizationProvider.get().getKey(); + } + Optional<OrganizationDto> org = dbClient.organizationDao().selectByKey(dbSession, effectiveKey); + checkFoundWithOptional(org, "No organization with key '%s'", key); + return org.get(); + } + + /** + * Similar to {@link UserGroupValidation#validateGroupName(String)} but kept internal. No need to publish + * this method in public API. + * @return the same description + */ + @CheckForNull + String validateDescription(@Nullable String description) { + checkArgument(description == null || description.length() <= DESCRIPTION_MAX_LENGTH, + "Description cannot be longer than %s characters", DESCRIPTION_MAX_LENGTH); + return description; + } + + void checkNameDoesNotExist(DbSession dbSession, String organizationUuid, String name) { + // There is no database constraint on column groups.name + // because MySQL cannot create a unique index + // on a UTF-8 VARCHAR larger than 255 characters on InnoDB + if (dbClient.groupDao().selectByName(dbSession, organizationUuid, name).isPresent()) { + throw new BadRequestException(format("Group '%s' already exists", name)); + } + } + + static WsUserGroups.Group.Builder toProtobuf(OrganizationDto organization, GroupDto group, int membersCount) { + WsUserGroups.Group.Builder wsGroup = WsUserGroups.Group.newBuilder() + .setId(group.getId()) + .setOrganization(organization.getKey()) + .setName(group.getName()) + .setMembersCount(membersCount); + if (group.getDescription() != null) { + wsGroup.setDescription(group.getDescription()); + } + return wsGroup; + } + + static void defineGroupWsParameters(WebService.NewAction action) { + defineGroupIdWsParameter(action); + defineGroupNameWsParameter(action); + } + + private static void defineGroupIdWsParameter(WebService.NewAction action) { + action.createParam(PARAM_GROUP_ID) + .setDescription("Group id") + .setExampleValue("42"); + } + + private static void defineGroupNameWsParameter(WebService.NewAction action) { + action.createParam(PARAM_ORGANIZATION_KEY) + .setDescription("Key of organization") + .setExampleValue("my-org") + .setSince("6.2"); + action.createParam(PARAM_GROUP_NAME) + .setDescription("Group name") + .setExampleValue("sonar-administrators"); + } + + static WebService.NewParam defineLoginWsParameter(WebService.NewAction action) { + return action.createParam(PARAM_LOGIN) + .setDescription("User login") + .setExampleValue("g.hopper"); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/RemoveUserAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/RemoveUserAction.java index 63e1eb405f0..995961517dd 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/RemoveUserAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/RemoveUserAction.java @@ -19,8 +19,6 @@ */ package org.sonar.server.usergroups.ws; -import javax.annotation.CheckForNull; -import org.sonar.api.security.DefaultGroups; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewAction; @@ -28,29 +26,27 @@ import org.sonar.api.server.ws.WebService.NewController; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.user.UserSession; import static java.lang.String.format; -import static org.sonar.api.security.DefaultGroups.isAnyone; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_ID; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_LOGIN; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.createGroupParameters; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.createLoginParameter; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_LOGIN; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineGroupWsParameters; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineLoginWsParameter; import static org.sonar.server.ws.WsUtils.checkFound; -import static org.sonar.server.ws.WsUtils.checkRequest; public class RemoveUserAction implements UserGroupsWsAction { private final DbClient dbClient; private final UserSession userSession; + private final GroupWsSupport support; - public RemoveUserAction(DbClient dbClient, UserSession userSession) { + public RemoveUserAction(DbClient dbClient, UserSession userSession, GroupWsSupport support) { this.dbClient = dbClient; this.userSession = userSession; + this.support = support; } @Override @@ -62,59 +58,25 @@ public class RemoveUserAction implements UserGroupsWsAction { .setPost(true) .setSince("5.2"); - createGroupParameters(action); - createLoginParameter(action); + defineGroupWsParameters(action); + defineLoginWsParameter(action); } @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - WsGroupRef wsGroupRef = WsGroupRef.newWsGroupRefFromUserGroupRequest(request); - String login = request.mandatoryParam(PARAM_LOGIN); + try (DbSession dbSession = dbClient.openSession(false)) { + GroupId group = support.findGroup(dbSession, request); - DbSession dbSession = dbClient.openSession(false); - try { - GroupDto group = getGroup(dbSession, wsGroupRef); - checkRequest(group != null, "It is not possible to remove a user from the '%s' group.", DefaultGroups.ANYONE); + String login = request.mandatoryParam(PARAM_LOGIN); UserDto user = getUser(dbSession, login); - UserGroupDto userGroup = new UserGroupDto().setGroupId(group.getId()).setUserId(user.getId()); - dbClient.userGroupDao().delete(dbSession, userGroup); + dbClient.userGroupDao().delete(dbSession, group.getId(), user.getId()); dbSession.commit(); - response.noContent(); - } finally { - dbClient.closeSession(dbSession); - } - - } - - /** - * - * @return null if it's the anyone group - */ - @CheckForNull - private GroupDto getGroup(DbSession dbSession, WsGroupRef group) { - Long groupId = group.id(); - String groupName = group.name(); - - if (isAnyone(groupName)) { - return null; - } - - GroupDto groupDto = null; - - if (groupId != null) { - groupDto = checkFound(dbClient.groupDao().selectById(dbSession, groupId), - "Group with id '%d' is not found", groupId); - } - if (groupName != null) { - groupDto = checkFound(dbClient.groupDao().selectByName(dbSession, groupName), - "Group with name '%s' is not found", groupName); + response.noContent(); } - - return groupDto; } private UserDto getUser(DbSession dbSession, String userLogin) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java index cc52587815c..e5deb2e92e2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/SearchAction.java @@ -19,28 +19,28 @@ */ package org.sonar.server.usergroups.ws; -import com.google.common.base.Function; -import com.google.common.collect.Collections2; import com.google.common.collect.Sets; import java.util.Arrays; -import java.util.Collection; import java.util.List; import java.util.Map; import java.util.Set; -import javax.annotation.Nonnull; -import org.apache.commons.lang.StringUtils; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService.NewController; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.text.JsonWriter; +import org.sonar.core.util.stream.Collectors; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.GroupDto; import org.sonar.server.es.SearchOptions; import org.sonar.server.user.UserSession; +import static org.apache.commons.lang.StringUtils.defaultIfBlank; import static org.sonar.server.es.SearchOptions.MAX_LIMIT; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY; public class SearchAction implements UserGroupsWsAction { @@ -52,15 +52,17 @@ public class SearchAction implements UserGroupsWsAction { private final DbClient dbClient; private final UserSession userSession; + private final GroupWsSupport groupWsSupport; - public SearchAction(DbClient dbClient, UserSession userSession) { + public SearchAction(DbClient dbClient, UserSession userSession, GroupWsSupport groupWsSupport) { this.dbClient = dbClient; this.userSession = userSession; + this.groupWsSupport = groupWsSupport; } @Override public void define(NewController context) { - context.createAction("search") + WebService.NewAction action = context.createAction("search") .setDescription("Search for user groups.<br>" + "Requires to be logged.") .setHandler(this) @@ -69,37 +71,37 @@ public class SearchAction implements UserGroupsWsAction { .addFieldsParam(ALL_FIELDS) .addPagingParams(100, MAX_LIMIT) .addSearchQuery("sonar-users", "names"); + + action.createParam(PARAM_ORGANIZATION_KEY) + .setDescription("Key of organization. If not set then groups are searched in default organization.") + .setExampleValue("my-org") + .setSince("6.2"); } @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn(); + int page = request.mandatoryParamAsInt(Param.PAGE); int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); SearchOptions options = new SearchOptions() .setPage(page, pageSize); - String query = StringUtils.defaultIfBlank(request.param(Param.TEXT_QUERY), ""); + String query = defaultIfBlank(request.param(Param.TEXT_QUERY), ""); Set<String> fields = neededFields(request); - DbSession dbSession = dbClient.openSession(false); - try { - int limit = dbClient.groupDao().countByQuery(dbSession, query); - List<GroupDto> groups = dbClient.groupDao().selectByQuery(dbSession, query, options.getOffset(), pageSize); - Collection<Long> groupIds = Collections2.transform(groups, new Function<GroupDto, Long>() { - @Override - public Long apply(@Nonnull GroupDto input) { - return input.getId(); - } - }); + try (DbSession dbSession = dbClient.openSession(false)) { + OrganizationDto organization = groupWsSupport.findOrganizationByKey(dbSession, request.param(PARAM_ORGANIZATION_KEY)); + + int limit = dbClient.groupDao().countByQuery(dbSession, organization.getUuid(), query); + List<GroupDto> groups = dbClient.groupDao().selectByQuery(dbSession, organization.getUuid(), query, options.getOffset(), pageSize); + List<Long> groupIds = groups.stream().map(GroupDto::getId).collect(Collectors.toList(groups.size())); Map<String, Integer> userCountByGroup = dbClient.groupMembershipDao().countUsersByGroups(dbSession, groupIds); JsonWriter json = response.newJsonWriter().beginObject(); options.writeJson(json, limit); writeGroups(json, groups, userCountByGroup, fields); json.endObject().close(); - } finally { - dbClient.closeSession(dbSession); } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UpdateAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UpdateAction.java index 76ea2367b20..22489e2090b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UpdateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UpdateAction.java @@ -20,40 +20,50 @@ package org.sonar.server.usergroups.ws; import java.util.Objects; +import java.util.Optional; import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService.NewAction; import org.sonar.api.server.ws.WebService.NewController; -import org.sonar.api.utils.text.JsonWriter; +import org.sonar.api.user.UserGroupValidation; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; +import org.sonar.db.organization.OrganizationDto; import org.sonar.db.user.GroupDto; -import org.sonar.server.exceptions.NotFoundException; +import org.sonar.db.user.GroupMembershipQuery; +import org.sonar.db.user.UserMembershipQuery; +import org.sonar.server.organization.DefaultOrganizationProvider; import org.sonar.server.platform.PersistentSettings; import org.sonar.server.user.UserSession; +import org.sonarqube.ws.WsUserGroups; -import static java.util.Collections.singletonList; import static org.sonar.api.CoreProperties.CORE_DEFAULT_GROUP; import static org.sonar.api.user.UserGroupValidation.GROUP_NAME_MAX_LENGTH; -import static org.sonar.db.MyBatis.closeQuietly; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.DESCRIPTION_MAX_LENGTH; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.PARAM_DESCRIPTION; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.PARAM_ID; -import static org.sonar.server.usergroups.ws.UserGroupUpdater.PARAM_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.DESCRIPTION_MAX_LENGTH; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_DESCRIPTION; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_ID; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.toProtobuf; +import static org.sonar.server.ws.WsUtils.checkFound; +import static org.sonar.server.ws.WsUtils.checkFoundWithOptional; +import static org.sonar.server.ws.WsUtils.writeProtobuf; public class UpdateAction implements UserGroupsWsAction { private final DbClient dbClient; private final UserSession userSession; + private final GroupWsSupport support; private final PersistentSettings persistentSettings; - private final UserGroupUpdater groupUpdater; + private final DefaultOrganizationProvider defaultOrganizationProvider; - public UpdateAction(DbClient dbClient, UserSession userSession, UserGroupUpdater groupUpdater, PersistentSettings persistentSettings) { + public UpdateAction(DbClient dbClient, UserSession userSession, GroupWsSupport support, PersistentSettings persistentSettings, + DefaultOrganizationProvider defaultOrganizationProvider) { this.dbClient = dbClient; - this.groupUpdater = groupUpdater; this.userSession = userSession; + this.support = support; this.persistentSettings = persistentSettings; + this.defaultOrganizationProvider = defaultOrganizationProvider; } @Override @@ -65,18 +75,19 @@ public class UpdateAction implements UserGroupsWsAction { .setResponseExample(getClass().getResource("example-update.json")) .setSince("5.2"); - action.createParam(PARAM_ID) + action.createParam(PARAM_GROUP_ID) .setDescription("Identifier of the group.") .setExampleValue("42") .setRequired(true); - action.createParam(PARAM_NAME) - .setDescription(String.format("New name for the group. A group name cannot be larger than %d characters and must be unique. " + - "The value 'anyone' (whatever the case) is reserved and cannot be used.", GROUP_NAME_MAX_LENGTH)) + action.createParam(PARAM_GROUP_NAME) + .setDescription(String.format("New optional name for the group. A group name cannot be larger than %d characters and must be unique. " + + "The value 'anyone' (whatever the case) is reserved and cannot be used. If value is empty or not defined, then name is not changed.", GROUP_NAME_MAX_LENGTH)) .setExampleValue("sonar-users"); - action.createParam(PARAM_DESCRIPTION) - .setDescription(String.format("New description for the group. A group description cannot be larger than %d characters.", DESCRIPTION_MAX_LENGTH)) + action.createParam(PARAM_GROUP_DESCRIPTION) + .setDescription(String.format("New optional description for the group. A group description cannot be larger than %d characters. " + + "If value is not defined, then description is not changed.", DESCRIPTION_MAX_LENGTH)) .setExampleValue("Default group for new users"); } @@ -84,42 +95,60 @@ public class UpdateAction implements UserGroupsWsAction { public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - Long groupId = request.mandatoryParamAsLong(PARAM_ID); - String name = request.param(PARAM_NAME); - String description = request.param(PARAM_DESCRIPTION); - - DbSession dbSession = dbClient.openSession(false); - try { + try (DbSession dbSession = dbClient.openSession(false)) { + long groupId = request.mandatoryParamAsLong(PARAM_GROUP_ID); GroupDto group = dbClient.groupDao().selectById(dbSession, groupId); - if (group == null) { - throw new NotFoundException(String.format("Could not find a user group with id '%s'.", groupId)); - } - String oldName = group.getName(); - if (name != null) { - groupUpdater.checkNameIsUnique(name, dbSession); - groupUpdater.validateName(name); - group.setName(name); - updateDefaultGroupIfNeeded(dbSession, oldName, name); + checkFound(group, "Could not find a user group with id '%s'.", groupId); + Optional<OrganizationDto> org = dbClient.organizationDao().selectByUuid(dbSession, group.getOrganizationUuid()); + checkFoundWithOptional(org, "Could not find organization with id '%s'.", group.getOrganizationUuid()); + + boolean changed = false; + String newName = request.param(PARAM_GROUP_NAME); + if (newName != null) { + changed = true; + UserGroupValidation.validateGroupName(newName); + support.checkNameDoesNotExist(dbSession, group.getOrganizationUuid(), newName); + + String oldName = group.getName(); + group.setName(newName); + updateDefaultGroupIfNeeded(dbSession, org.get(), oldName, newName); } + + String description = request.param(PARAM_GROUP_DESCRIPTION); if (description != null) { - groupUpdater.validateDescription(description); - group.setDescription(description); + changed = true; + group.setDescription(support.validateDescription(description)); + } + + if (changed) { + dbClient.groupDao().update(dbSession, group); + dbSession.commit(); } - dbClient.groupDao().update(dbSession, group); - dbSession.commit(); - - JsonWriter json = response.newJsonWriter().beginObject(); - groupUpdater.writeGroup(json, group, dbClient.groupMembershipDao().countUsersByGroups(dbSession, singletonList(groupId)).get(group.getName())); - json.endObject().close(); - } finally { - closeQuietly(dbSession); + + writeResponse(dbSession, request, response, org.get(), group); } } - private void updateDefaultGroupIfNeeded(DbSession dbSession, String oldName, String newName) { - String defaultGroupName = persistentSettings.getString(CORE_DEFAULT_GROUP); - if (Objects.equals(defaultGroupName, oldName)) { - persistentSettings.saveProperty(dbSession, CORE_DEFAULT_GROUP, newName); + private void updateDefaultGroupIfNeeded(DbSession dbSession, OrganizationDto org, String oldName, String newName) { + // The feature "default group" relies on a property. As organization properties are + // not implemented yet, default groups are not supported on non-default organizations + if (defaultOrganizationProvider.get().getUuid().equals(org.getUuid())) { + String defaultGroupName = persistentSettings.getString(CORE_DEFAULT_GROUP); + if (Objects.equals(defaultGroupName, oldName)) { + persistentSettings.saveProperty(dbSession, CORE_DEFAULT_GROUP, newName); + } } } + + private void writeResponse(DbSession dbSession, Request request, Response response, OrganizationDto organization, GroupDto group) { + UserMembershipQuery query = UserMembershipQuery.builder() + .groupId(group.getId()) + .membership(GroupMembershipQuery.IN) + .build(); + int membersCount = dbClient.groupMembershipDao().countMembers(dbSession, query); + + WsUserGroups.UpdateResponse.Builder respBuilder = WsUserGroups.UpdateResponse.newBuilder(); + respBuilder.setGroup(toProtobuf(organization, group, membersCount)); + writeProtobuf(respBuilder.build(), request, response); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupUpdater.java deleted file mode 100644 index de2e7bd5960..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupUpdater.java +++ /dev/null @@ -1,74 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.usergroups.ws; - -import com.google.common.base.Preconditions; -import org.sonar.api.server.ServerSide; -import org.sonar.api.user.UserGroupValidation; -import org.sonar.api.utils.text.JsonWriter; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; -import org.sonar.db.user.GroupDto; -import org.sonar.server.exceptions.BadRequestException; - -@ServerSide -public class UserGroupUpdater { - - static final String PARAM_ID = "id"; - static final String PARAM_DESCRIPTION = "description"; - static final String PARAM_NAME = "name"; - - // Database column size should be 500 (since migration #353), - // but on some instances, column size is still 255, - // hence the validation is done with 255 - static final int DESCRIPTION_MAX_LENGTH = 200; - - private final DbClient dbClient; - - public UserGroupUpdater(DbClient dbClient) { - this.dbClient = dbClient; - } - - protected void validateName(String name) { - UserGroupValidation.validateGroupName(name); - } - - protected void checkNameIsUnique(String name, DbSession session) { - // There is no database constraint on column groups.name - // because MySQL cannot create a unique index - // on a UTF-8 VARCHAR larger than 255 characters on InnoDB - if (dbClient.groupDao().selectByName(session, name) != null) { - throw new BadRequestException(String.format("Name '%s' is already taken", name)); - } - } - - protected void validateDescription(String description) { - Preconditions.checkArgument(description.length() <= DESCRIPTION_MAX_LENGTH, String.format("Description cannot be longer than %d characters", DESCRIPTION_MAX_LENGTH)); - } - - protected void writeGroup(JsonWriter json, GroupDto group, int membersCount) { - json.name("group").beginObject() - .prop(PARAM_ID, group.getId().toString()) - .prop(PARAM_NAME, group.getName()) - .prop(PARAM_DESCRIPTION, group.getDescription()) - .prop("membersCount", membersCount) - .endObject(); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsModule.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsModule.java index 68d24901aa3..acc032f76f1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsModule.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsModule.java @@ -27,8 +27,7 @@ public class UserGroupsModule extends Module { protected void configureModule() { add( UserGroupsWs.class, - UserGroupUpdater.class, - UserGroupFinder.class, + GroupWsSupport.class, // actions SearchAction.class, CreateAction.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsWsParameters.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsWsParameters.java deleted file mode 100644 index dfb54c5d2aa..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UserGroupsWsParameters.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.usergroups.ws; - -import org.sonar.api.server.ws.WebService.NewAction; -import org.sonar.api.server.ws.WebService.NewParam; - -public class UserGroupsWsParameters { - static final String PARAM_GROUP_NAME = "name"; - static final String PARAM_GROUP_ID = "id"; - static final String PARAM_LOGIN = "login"; - - private UserGroupsWsParameters() { - // static methods only - } - - static void createGroupParameters(NewAction action) { - createGroupIdParameter(action); - createGroupNameParameter(action); - } - - private static void createGroupIdParameter(NewAction action) { - action.createParam(PARAM_GROUP_ID) - .setDescription("Group id") - .setExampleValue("42"); - } - - private static void createGroupNameParameter(NewAction action) { - action.createParam(PARAM_GROUP_NAME) - .setDescription("Group name") - .setExampleValue("sonar-administrators"); - } - - static NewParam createLoginParameter(NewAction action) { - return action.createParam(PARAM_LOGIN) - .setDescription("User login") - .setExampleValue("g.hopper"); - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java index 468d0a43d09..604fbc11ce1 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/UsersAction.java @@ -31,15 +31,13 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.core.permission.GlobalPermissions; import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; -import org.sonar.db.user.GroupDto; import org.sonar.db.user.GroupMembershipQuery; import org.sonar.db.user.UserMembershipDto; import org.sonar.db.user.UserMembershipQuery; import org.sonar.server.user.UserSession; import static org.sonar.api.utils.Paging.forPageIndex; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.createGroupParameters; +import static org.sonar.server.usergroups.ws.GroupWsSupport.defineGroupWsParameters; public class UsersAction implements UserGroupsWsAction { @@ -48,13 +46,13 @@ public class UsersAction implements UserGroupsWsAction { private static final String FIELD_LOGIN = "login"; private final DbClient dbClient; - private final UserGroupFinder userGroupFinder; private final UserSession userSession; + private final GroupWsSupport support; - public UsersAction(DbClient dbClient, UserGroupFinder userGroupFinder, UserSession userSession) { + public UsersAction(DbClient dbClient, UserSession userSession, GroupWsSupport support) { this.dbClient = dbClient; - this.userGroupFinder = userGroupFinder; this.userSession = userSession; + this.support = support; } @Override @@ -68,26 +66,23 @@ public class UsersAction implements UserGroupsWsAction { .addSearchQuery("freddy", "names", "logins") .addPagingParams(25); - createGroupParameters(action); + defineGroupWsParameters(action); } @Override public void handle(Request request, Response response) throws Exception { userSession.checkLoggedIn().checkPermission(GlobalPermissions.SYSTEM_ADMIN); - WsGroupRef wsGroupRef = WsGroupRef.newWsGroupRefFromUserGroupRequest(request); int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); int page = request.mandatoryParamAsInt(Param.PAGE); String queryString = request.param(Param.TEXT_QUERY); String selected = request.mandatoryParam(Param.SELECTED); - DbSession dbSession = dbClient.openSession(false); - try { - GroupDto group = userGroupFinder.getGroup(dbSession, wsGroupRef); - long groupId = group.getId(); + try (DbSession dbSession = dbClient.openSession(false)) { + GroupId group = support.findGroup(dbSession, request); UserMembershipQuery query = UserMembershipQuery.builder() - .groupId(groupId) + .groupId(group.getId()) .memberSearch(queryString) .membership(getMembership(selected)) .pageIndex(page) @@ -101,8 +96,6 @@ public class UsersAction implements UserGroupsWsAction { writeMembers(json, users); writePaging(json, paging); json.endObject().close(); - } finally { - MyBatis.closeQuietly(dbSession); } } @@ -124,7 +117,7 @@ public class UsersAction implements UserGroupsWsAction { .prop("total", paging.total()); } - private String getMembership(String selected) { + private static String getMembership(String selected) { SelectionMode selectionMode = SelectionMode.fromParam(selected); String membership = GroupMembershipQuery.ANY; if (SelectionMode.SELECTED == selectionMode) { diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/WsGroupRef.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/WsGroupRef.java deleted file mode 100644 index a95b34fa071..00000000000 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/WsGroupRef.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2016 SonarSource SA - * mailto:contact AT sonarsource DOT com - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 3 of the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.server.usergroups.ws; - -import javax.annotation.CheckForNull; -import javax.annotation.Nullable; -import org.sonar.api.server.ws.Request; - -import static org.sonar.server.ws.WsUtils.checkRequest; - -/** - * Group from a WS request. Guaranties the group id or the group name is provided, not both. - */ -public class WsGroupRef { - - private final Long id; - private final String name; - - private WsGroupRef(@Nullable Long id, @Nullable String name) { - checkRequest(id != null ^ name != null, "Group name or group id must be provided, not both."); - - this.id = id; - this.name = name; - } - - public static WsGroupRef newWsGroupRef(@Nullable Long id, @Nullable String name) { - return new WsGroupRef(id, name); - } - - public static WsGroupRef newWsGroupRefFromUserGroupRequest(Request wsRequest) { - Long id = wsRequest.paramAsLong(UserGroupsWsParameters.PARAM_GROUP_ID); - String name = wsRequest.param(UserGroupsWsParameters.PARAM_GROUP_NAME); - - return new WsGroupRef(id, name); - } - - @CheckForNull - public Long id() { - return this.id; - } - - @CheckForNull - public String name() { - return this.name; - } -} diff --git a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/package-info.java b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/package-info.java index d3324e608f4..7ba0a0da3c9 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/package-info.java +++ b/server/sonar-server/src/main/java/org/sonar/server/usergroups/ws/package-info.java @@ -21,4 +21,3 @@ package org.sonar.server.usergroups.ws; import javax.annotation.ParametersAreNonnullByDefault; - diff --git a/server/sonar-server/src/main/resources/org/sonar/server/usergroups/ws/example-create.json b/server/sonar-server/src/main/resources/org/sonar/server/usergroups/ws/example-create.json index 00f5eb9f6b2..91ea7df4d1a 100644 --- a/server/sonar-server/src/main/resources/org/sonar/server/usergroups/ws/example-create.json +++ b/server/sonar-server/src/main/resources/org/sonar/server/usergroups/ws/example-create.json @@ -1,6 +1,7 @@ { "group": { "id": "42", + "organization": "my-org", "name": "some-product-bu", "description": "Business Unit for Some Awesome Product", "membersCount": 0 diff --git a/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java b/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java index 00b83ec3de6..ebffd03f705 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/user/ServerUserSessionTest.java @@ -30,11 +30,8 @@ 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.component.ComponentDbTester; import org.sonar.db.component.ComponentDto; import org.sonar.db.component.ComponentTesting; -import org.sonar.db.permission.GroupPermissionDto; -import org.sonar.db.permission.UserPermissionDto; import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.ForbiddenException; @@ -60,22 +57,19 @@ public class ServerUserSessionTest { }}.setLogin("regular_user"); @Rule - public DbTester dbTester = DbTester.create(System2.INSTANCE); + public DbTester db = DbTester.create(System2.INSTANCE); @Rule public ExpectedException expectedException = ExpectedException.none(); - private ComponentDbTester componentDbTester = new ComponentDbTester(dbTester); - private DbClient dbClient = dbTester.getDbClient(); - private DbSession dbSession = dbTester.getSession(); + private DbClient dbClient = db.getDbClient(); private UserDto userDto = newUserDto().setLogin(LOGIN); private ComponentDto project; @Before public void setUp() throws Exception { - project = componentDbTester.insertComponent(ComponentTesting.newProjectDto(PROJECT_UUID)); - componentDbTester.insertComponent(ComponentTesting.newFileDto(project, null, FILE_UUID).setKey(FILE_KEY)); - dbClient.userDao().insert(dbSession, userDto); - dbSession.commit(); + project = db.components().insertComponent(ComponentTesting.newProjectDto(PROJECT_UUID)); + db.components().insertComponent(ComponentTesting.newFileDto(project, null, FILE_UUID).setKey(FILE_KEY)); + db.users().insertUser(userDto); } @Test @@ -221,8 +215,8 @@ public class ServerUserSessionTest { @Test public void checkComponentPermission_throws_FE_when_user_has_not_permission_for_specified_key_in_db() { - ComponentDto project2 = componentDbTester.insertComponent(ComponentTesting.newProjectDto()); - ComponentDto file2 = componentDbTester.insertComponent(ComponentTesting.newFileDto(project2, null)); + ComponentDto project2 = db.components().insertComponent(ComponentTesting.newProjectDto()); + ComponentDto file2 = db.components().insertComponent(ComponentTesting.newFileDto(project2, null)); addProjectPermissions(project, UserRole.USER); UserSession session = newUserSession(userDto); @@ -243,8 +237,8 @@ public class ServerUserSessionTest { @Test public void checkComponentPermission_fails_with_FE_when_project_of_specified_uuid_can_not_be_found() { - ComponentDto project2 = componentDbTester.insertComponent(ComponentTesting.newProjectDto()); - ComponentDto file2 = componentDbTester.insertComponent(ComponentTesting.newFileDto(project2, null) + ComponentDto project2 = db.components().insertComponent(ComponentTesting.newProjectDto()); + ComponentDto file2 = db.components().insertComponent(ComponentTesting.newFileDto(project2, null) // Simulate file is linked to an invalid project .setProjectUuid("INVALID")); addProjectPermissions(project, UserRole.USER); @@ -307,7 +301,7 @@ public class ServerUserSessionTest { @Test public void has_global_permission_for_anonymous() throws Exception { - addAnonymousPermissions(null, "profileadmin", "admin"); + addAnyonePermissions(null, "profileadmin", "admin"); UserSession session = newAnonymousSession(); assertThat(session.getLogin()).isNull(); @@ -320,7 +314,7 @@ public class ServerUserSessionTest { @Test public void has_project_permission_for_anonymous() throws Exception { - addAnonymousPermissions(project, UserRole.USER); + addAnyonePermissions(project, UserRole.USER); UserSession session = newAnonymousSession(); assertThat(session.hasComponentPermission(UserRole.USER, FILE_KEY)).isTrue(); @@ -344,20 +338,24 @@ public class ServerUserSessionTest { addPermissions(component, permissions); } - private void addPermissions( @Nullable ComponentDto component, String... permissions) { + private void addPermissions(@Nullable ComponentDto component, String... permissions) { for (String permission : permissions) { - dbClient.userPermissionDao().insert(dbSession, new UserPermissionDto(permission, userDto.getId(), component == null ? null : component.getId())); + if (component == null) { + db.users().insertPermissionOnUser(userDto, permission); + } else { + db.users().insertProjectPermissionOnUser(userDto, permission, component); + } } - dbSession.commit(); } - private void addAnonymousPermissions(@Nullable ComponentDto component, String... permissions) { + private void addAnyonePermissions(@Nullable ComponentDto component, String... permissions) { for (String permission : permissions) { - dbClient.roleDao().insertGroupRole(dbSession, new GroupPermissionDto() - .setRole(permission) - .setResourceId(component == null ? null : component.getId())); + if (component == null) { + db.users().insertPermissionOnAnyone(permission); + } else { + db.users().insertProjectPermissionOnAnyone(permission, component); + } } - dbSession.commit(); } private void expectInsufficientPrivilegesForbiddenException() { @@ -365,5 +363,4 @@ public class ServerUserSessionTest { expectedException.expectMessage("Insufficient privileges"); } - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/AddUserActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/AddUserActionTest.java index 58b4f5137a1..dc4f9f555f3 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/AddUserActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/AddUserActionTest.java @@ -19,164 +19,153 @@ */ package org.sonar.server.usergroups.ws; -import com.google.common.collect.Multimap; -import java.util.Arrays; -import org.apache.commons.lang.StringUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; 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.user.GroupDao; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; import org.sonar.db.user.GroupDto; -import org.sonar.db.user.GroupMembershipDao; -import org.sonar.db.user.UserDao; import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDao; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.exceptions.UnauthorizedException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_LOGIN; - +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_LOGIN; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY; public class AddUserActionTest { @Rule public DbTester db = DbTester.create(System2.INSTANCE); @Rule - public final UserSessionRule userSession = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule - public final ExpectedException expectedException = ExpectedException.none(); + public ExpectedException expectedException = ExpectedException.none(); + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); private WsTester ws; - private GroupDao groupDao; - private UserDao userDao; - private GroupMembershipDao groupMembershipDao; - private UserGroupDao userGroupDao; - private DbSession dbSession; @Before public void setUp() { - dbSession = db.getSession(); - DbClient dbClient = db.getDbClient(); - - groupDao = dbClient.groupDao(); - userDao = dbClient.userDao(); - groupMembershipDao = dbClient.groupMembershipDao(); - userGroupDao = dbClient.userGroupDao(); - - ws = new WsTester(new UserGroupsWs(new AddUserAction(dbClient, new UserGroupFinder(dbClient), userSession))); + ws = new WsTester(new UserGroupsWs(new AddUserAction(db.getDbClient(), userSession, newGroupWsSupport()))); } @Test - public void add_user_nominal() throws Exception { - GroupDto group = insertGroup("admins"); - UserDto user = insertUser("my-admin"); - dbSession.commit(); + public void add_user_to_group_referenced_by_its_id() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "admins"); + UserDto user = db.users().insertUser("my-admin"); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .containsOnly(group.getName()); + assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(group.getId()); } @Test - public void add_user_with_group_name() throws Exception { - GroupDto group = insertGroup("group_name"); - UserDto user = insertUser("user_login"); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .isEmpty(); - dbSession.commit(); + public void add_user_to_group_referenced_by_its_name() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a-group"); + UserDto user = db.users().insertUser("user_login"); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); + newRequest() + .setParam(PARAM_GROUP_NAME, group.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute() + .assertNoContent(); + + assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(group.getId()); + } + + @Test + public void add_user_to_group_referenced_by_its_name_and_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, "a-group"); + UserDto user = db.users().insertUser("user_login"); + + loginAsAdmin(); newRequest() + .setParam(PARAM_ORGANIZATION_KEY, org.getKey()) .setParam(PARAM_GROUP_NAME, group.getName()) .setParam(PARAM_LOGIN, user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .containsOnly(group.getName()); + assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(group.getId()); } @Test public void add_user_to_another_group() throws Exception { - GroupDto admins = insertGroup("admins"); - GroupDto users = insertGroup("users"); - UserDto user = insertUser("my-admin"); - insertMember(users.getId(), user.getId()); - dbSession.commit(); + OrganizationDto defaultOrg = defaultOrganizationProvider.getDto(); + GroupDto admins = db.users().insertGroup(defaultOrg, "admins"); + GroupDto users = db.users().insertGroup(defaultOrg, "users"); + UserDto user = db.users().insertUser("my-admin"); + db.users().insertMember(users, user); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", admins.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .containsOnly(admins.getName(), users.getName()); + assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(admins.getId(), users.getId()); } @Test - public void add_user_already_in_group() throws Exception { - GroupDto users = insertGroup("users"); - UserDto user = insertUser("my-admin"); - insertMember(users.getId(), user.getId()); - dbSession.commit(); + public void user_is_already_member_of_group() throws Exception { + GroupDto users = db.users().insertGroup(defaultOrganizationProvider.getDto(), "users"); + UserDto user = db.users().insertUser("my-admin"); + db.users().insertMember(users, user); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", users.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .containsOnly(users.getName()); + // do not insert duplicated row + assertThat(db.users().selectGroupIdsOfUser(user)).hasSize(1).containsOnly(users.getId()); } @Test - public void add_another_user_to_group() throws Exception { - GroupDto users = insertGroup("user"); - UserDto user1 = insertUser("user1"); - UserDto user2 = insertUser("user2"); - insertMember(users.getId(), user1.getId()); - dbSession.commit(); + public void group_has_multiple_members() throws Exception { + GroupDto users = db.users().insertGroup(defaultOrganizationProvider.getDto(), "user"); + UserDto user1 = db.users().insertUser("user1"); + UserDto user2 = db.users().insertUser("user2"); + db.users().insertMember(users, user1); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", users.getId().toString()) .setParam("login", user2.getLogin()) .execute() .assertNoContent(); - Multimap<String, String> groupsByLogins = groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user1.getLogin(), user2.getLogin())); - assertThat(groupsByLogins.get(user1.getLogin())).containsOnly(users.getName()); - assertThat(groupsByLogins.get(user2.getLogin())).containsOnly(users.getName()); + assertThat(db.users().selectGroupIdsOfUser(user1)).containsOnly(users.getId()); + assertThat(db.users().selectGroupIdsOfUser(user2)).containsOnly(users.getId()); } @Test - public void unknown_group() throws Exception { - UserDto user = insertUser("my-admin"); - dbSession.commit(); + public void fail_if_group_does_not_exist() throws Exception { + UserDto user = db.users().insertUser("my-admin"); expectedException.expect(NotFoundException.class); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", "42") .setParam("login", user.getLogin()) @@ -184,34 +173,41 @@ public class AddUserActionTest { } @Test - public void unknown_user() throws Exception { - GroupDto group = insertGroup("admins"); - dbSession.commit(); + public void fail_if_user_does_not_exist() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "admins"); expectedException.expect(NotFoundException.class); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) .setParam("login", "my-admin") .execute(); } + @Test + public void fail_if_not_administrator() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "admins"); + UserDto user = db.users().insertUser("my-admin"); + + expectedException.expect(UnauthorizedException.class); + + newRequest() + .setParam("id", group.getId().toString()) + .setParam("login", user.getLogin()) + .execute(); + } + private WsTester.TestRequest newRequest() { return ws.newPostRequest("api/user_groups", "add_user"); } - private GroupDto insertGroup(String groupName) { - return groupDao.insert(dbSession, new GroupDto() - .setName(groupName) - .setDescription(StringUtils.capitalize(groupName))); + private void loginAsAdmin() { + userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } - private UserDto insertUser(String login) { - return userDao.insert(dbSession, new UserDto().setLogin(login).setName(login).setActive(true)); + private GroupWsSupport newGroupWsSupport() { + return new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); } - private void insertMember(long groupId, long userId) { - userGroupDao.insert(dbSession, new UserGroupDto().setGroupId(groupId).setUserId(userId)); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/CreateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/CreateActionTest.java index 0118dd9993d..0953039a70f 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/CreateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/CreateActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.usergroups.ws; -import java.net.HttpURLConnection; import org.apache.commons.lang.StringUtils; import org.junit.Before; import org.junit.Rule; @@ -27,16 +26,19 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; 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.user.GroupDao; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; import org.sonar.db.user.GroupDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.ServerException; +import org.sonar.server.organization.DefaultOrganization; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; public class CreateActionTest { @@ -47,37 +49,62 @@ public class CreateActionTest { @Rule public ExpectedException expectedException = ExpectedException.none(); + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); private WsTester ws; - private GroupDao groupDao; - private DbSession dbSession; @Before public void setUp() { - DbClient dbClient = db.getDbClient(); - groupDao = dbClient.groupDao(); - dbSession = db.getSession(); + ws = new WsTester(new UserGroupsWs(new CreateAction(db.getDbClient(), userSession, newGroupWsSupport()))); + } + + @Test + public void create_group_on_default_organization() throws Exception { + loginAsAdmin(); - ws = new WsTester(new UserGroupsWs(new CreateAction(dbClient, userSession, new UserGroupUpdater(dbClient)))); + newRequest() + .setParam("name", "some-product-bu") + .setParam("description", "Business Unit for Some Awesome Product") + .execute() + .assertJson("{" + + " \"group\": {" + + " \"organization\": \"" + getDefaultOrganization().getKey() + "\"," + + " \"name\": \"some-product-bu\"," + + " \"description\": \"Business Unit for Some Awesome Product\"," + + " \"membersCount\": 0" + + " }" + + "}"); + + assertThat(db.users().selectGroup(defaultOrganizationProvider.getDto(), "some-product-bu")).isPresent(); } @Test - public void create_nominal() throws Exception { + public void create_group_on_specific_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + loginAsAdmin(); newRequest() + .setParam("organization", org.getKey()) .setParam("name", "some-product-bu") .setParam("description", "Business Unit for Some Awesome Product") - .execute().assertJson("{" + + .execute() + .assertJson("{" + " \"group\": {" + + " \"organization\": \"" + org.getKey() + "\"," + " \"name\": \"some-product-bu\"," + " \"description\": \"Business Unit for Some Awesome Product\"," + " \"membersCount\": 0" + " }" + "}"); + + GroupDto createdGroup = db.users().selectGroup(org, "some-product-bu").get(); + assertThat(createdGroup.getId()).isNotNull(); + assertThat(createdGroup.getOrganizationUuid()).isEqualTo(org.getUuid()); } @Test(expected = ForbiddenException.class) public void require_admin_permission() throws Exception { userSession.login("not-admin"); + newRequest() .setParam("name", "some-product-bu") .setParam("description", "Business Unit for Some Awesome Product") @@ -85,7 +112,7 @@ public class CreateActionTest { } @Test(expected = IllegalArgumentException.class) - public void name_too_short() throws Exception { + public void fail_if_name_is_too_short() throws Exception { loginAsAdmin(); newRequest() .setParam("name", "") @@ -93,7 +120,7 @@ public class CreateActionTest { } @Test(expected = IllegalArgumentException.class) - public void name_too_long() throws Exception { + public void fail_if_name_is_too_long() throws Exception { loginAsAdmin(); newRequest() .setParam("name", StringUtils.repeat("a", 255 + 1)) @@ -101,7 +128,7 @@ public class CreateActionTest { } @Test(expected = IllegalArgumentException.class) - public void forbidden_name() throws Exception { + public void fail_if_name_is_anyone() throws Exception { loginAsAdmin(); newRequest() .setParam("name", "AnYoNe") @@ -109,27 +136,62 @@ public class CreateActionTest { } @Test - public void non_unique_name() throws Exception { - String groupName = "conflicting-name"; - groupDao.insert(dbSession, new GroupDto() - .setName(groupName)); - db.commit(); + public void fail_if_group_with_same_name_already_exists() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "the-group"); expectedException.expect(ServerException.class); - expectedException.expectMessage("already taken"); + expectedException.expectMessage("Group '" + group.getName() + "' already exists"); loginAsAdmin(); newRequest() - .setParam("name", groupName) - .execute().assertStatus(HttpURLConnection.HTTP_CONFLICT); + .setParam("name", group.getName()) + .execute(); + } + + @Test + public void fail_if_group_with_same_name_already_exists_in_the_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, "the-group"); + + expectedException.expect(ServerException.class); + expectedException.expectMessage("Group '" + group.getName() + "' already exists"); + + loginAsAdmin(); + newRequest() + .setParam("organization", org.getKey()) + .setParam("name", group.getName()) + .execute(); + } + + @Test + public void add_group_with_a_name_that_already_exists_in_another_organization() throws Exception { + String name = "the-group"; + OrganizationDto org1 = OrganizationTesting.insert(db, newOrganizationDto()); + OrganizationDto org2 = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org1, name); + + loginAsAdmin(); + newRequest() + .setParam("organization", org2.getKey()) + .setParam("name", name) + .execute() + .assertJson("{" + + " \"group\": {" + + " \"organization\": \"" + org2.getKey() + "\"," + + " \"name\": \"" + group.getName() + "\"," + + " }" + + "}"); + + assertThat(db.users().selectGroups(org1)).extracting(GroupDto::getName).containsOnly(name); + assertThat(db.users().selectGroups(org2)).extracting(GroupDto::getName).containsOnly(name); } @Test(expected = IllegalArgumentException.class) - public void description_too_long() throws Exception { + public void fail_if_description_is_too_long() throws Exception { loginAsAdmin(); newRequest() - .setParam("name", "long-group-description-is-looooooooooooong") - .setParam("description", StringUtils.repeat("a", 200 + 1)) + .setParam("name", "long-desc") + .setParam("description", StringUtils.repeat("a", 1_000)) .execute(); } @@ -140,4 +202,12 @@ public class CreateActionTest { private void loginAsAdmin() { userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } + + private GroupWsSupport newGroupWsSupport() { + return new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); + } + + private DefaultOrganization getDefaultOrganization() { + return defaultOrganizationProvider.get(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java index 05968b480d5..2cdd2e07a25 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/DeleteActionTest.java @@ -28,30 +28,24 @@ import org.sonar.api.config.MapSettings; import org.sonar.api.config.Settings; 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.GroupPermissionDao; -import org.sonar.db.permission.GroupPermissionDto; -import org.sonar.db.permission.UserPermissionDto; -import org.sonar.db.permission.template.PermissionTemplateDao; -import org.sonar.db.user.GroupDao; -import org.sonar.db.user.GroupDbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.component.ComponentTesting; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; import org.sonar.db.user.GroupDto; -import org.sonar.db.user.RoleDao; -import org.sonar.db.user.UserDbTester; import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDao; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.db.user.GroupTesting.newGroupDto; -import static org.sonar.db.user.UserTesting.newUserDto; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; +import static org.sonar.core.permission.GlobalPermissions.SYSTEM_ADMIN; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY; public class DeleteActionTest { @@ -61,127 +55,164 @@ public class DeleteActionTest { public ExpectedException expectedException = ExpectedException.none(); @Rule public DbTester db = DbTester.create(System2.INSTANCE); - GroupDbTester groupDb = new GroupDbTester(db); - UserDbTester userDb = new UserDbTester(db); - DbClient dbClient = db.getDbClient(); - DbSession dbSession = db.getSession(); - GroupDao groupDao = dbClient.groupDao(); - UserGroupDao userGroupDao = dbClient.userGroupDao(); - RoleDao roleDao = dbClient.roleDao(); - PermissionTemplateDao permissionTemplateDao = dbClient.permissionTemplateDao(); - GroupPermissionDao groupPermissionDao = dbClient.groupPermissionDao(); + private ComponentDbTester componentTester = new ComponentDbTester(db); + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); + private GroupDto defaultGroup; private WsTester ws; - private Long defaultGroupId; @Before public void setUp() { + defaultGroup = db.users().insertGroup(defaultOrganizationProvider.getDto(), CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE); Settings settings = new MapSettings().setProperty(CoreProperties.CORE_DEFAULT_GROUP, CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE); - GroupDto defaultGroup = groupDao.insert(dbSession, new GroupDto().setName(CoreProperties.CORE_DEFAULT_GROUP_DEFAULT_VALUE)); - defaultGroupId = defaultGroup.getId(); - dbSession.commit(); ws = new WsTester(new UserGroupsWs( new DeleteAction( - dbClient, - new UserGroupFinder(dbClient), + db.getDbClient(), userSession, - settings))); + newGroupWsSupport(), + settings, defaultOrganizationProvider))); } @Test - public void delete_simple() throws Exception { - GroupDto group = groupDao.insert(dbSession, new GroupDto().setName("to-delete")); - dbSession.commit(); + public void delete_by_id() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-delete"); loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) - .execute().assertNoContent(); + .execute() + .assertNoContent(); + + assertThat(db.users().selectGroupById(group.getId())).isNull(); } @Test - public void delete_with_group_name() throws Exception { - GroupDto group = groupDao.insert(dbSession, newGroupDto().setName("group_name")); - assertThat(groupDao.selectById(dbSession, group.getId())).isNotNull(); - dbSession.commit(); + public void delete_by_name_on_default_organization() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-delete"); loginAsAdmin(); newRequest() .setParam(PARAM_GROUP_NAME, group.getName()) - .execute().assertNoContent(); + .execute() + .assertNoContent(); + + assertThat(db.users().selectGroupById(group.getId())).isNull(); + } + + @Test + public void delete_by_name_and_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, "to-delete"); + + loginAsAdmin(); + newRequest() + .setParam(PARAM_ORGANIZATION_KEY, org.getKey()) + .setParam(PARAM_GROUP_NAME, group.getName()) + .execute() + .assertNoContent(); + + assertThat(db.users().selectGroupById(group.getId())).isNull(); + } + + @Test + public void delete_by_name_fails_if_organization_is_not_correct() throws Exception { + OrganizationDto org = newOrganizationDto().setUuid("org1"); + OrganizationTesting.insert(db, org); + + loginAsAdmin(); + + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("No organization with key 'org1'"); - assertThat(groupDao.selectById(dbSession, group.getId())).isNull(); + newRequest() + .setParam(PARAM_ORGANIZATION_KEY, "org1") + .setParam(PARAM_GROUP_NAME, "a-group") + .execute(); } @Test - public void delete_with_members() throws Exception { - GroupDto group = groupDao.insert(dbSession, new GroupDto().setName("to-delete")); - userGroupDao.insert(dbSession, new UserGroupDto().setGroupId(group.getId()).setUserId(42L)); - dbSession.commit(); + public void delete_members() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted"); + UserDto user = db.users().insertUser("a-user"); + db.users().insertMember(group, user); loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) - .execute().assertNoContent(); + .execute() + .assertNoContent(); - assertThat(db.select("SELECT group_id FROM groups_users")).isEmpty(); + assertThat(db.countRowsOfTable("groups_users")).isEqualTo(0); } @Test - public void delete_with_permissions() throws Exception { - GroupDto group = groupDao.insert(dbSession, new GroupDto().setName("to-delete")); - roleDao.insertGroupRole(dbSession, new GroupPermissionDto().setGroupId(group.getId()).setResourceId(42L).setRole(UserRole.ADMIN)); - dbSession.commit(); + public void delete_permissions() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted"); + ComponentDto project = componentTester.insertComponent(ComponentTesting.newProjectDto()); + db.users().insertProjectPermissionOnGroup(group, UserRole.ADMIN, project); loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) - .execute().assertNoContent(); + .execute() + .assertNoContent(); - assertThat(db.select("SELECT group_id FROM group_roles")).isEmpty(); + assertThat(db.countRowsOfTable("group_roles")).isEqualTo(0); } @Test - public void delete_with_permission_templates() throws Exception { - GroupDto group = groupDao.insert(dbSession, new GroupDto().setName("to-delete")); - permissionTemplateDao.insertGroupPermission(dbSession, 42L, group.getId(), UserRole.ADMIN); - dbSession.commit(); + public void delete_permission_templates() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "to-be-deleted"); + // TODO loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) .execute().assertNoContent(); - assertThat(db.select("SELECT group_id FROM perm_templates_groups")).isEmpty(); + assertThat(db.countRowsOfTable("perm_templates_groups")).isEqualTo(0); } @Test(expected = NotFoundException.class) - public void not_found() throws Exception { + public void fail_if_id_does_not_exist() throws Exception { loginAsAdmin(); newRequest() - .setParam("id", String.valueOf(defaultGroupId + 1L)) + .setParam("id", String.valueOf(defaultGroup.getId() + 123)) .execute(); } @Test(expected = IllegalArgumentException.class) - public void cannot_delete_default_group() throws Exception { + public void cannot_delete_default_group_of_default_organization() throws Exception { + loginAsAdmin(); + newRequest() + .setParam("id", defaultGroup.getId().toString()) + .execute(); + } + + @Test + public void delete_group_of_an_organization_even_if_name_is_default_group_of_default_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, defaultGroup.getName()); + loginAsAdmin(); newRequest() - .setParam("id", defaultGroupId.toString()) + .setParam("id", group.getId().toString()) .execute(); + + assertThat(db.users().selectGroupById(defaultGroup.getId())).isNotNull(); + assertThat(db.users().selectGroupById(group.getId())).isNull(); } @Test public void cannot_delete_last_system_admin_group() throws Exception { - GroupDto group = groupDb.insertGroup(newGroupDto().setName("system-admins")); - roleDao.insertGroupRole(dbSession, new GroupPermissionDto().setGroupId(group.getId()).setRole(GlobalPermissions.SYSTEM_ADMIN)); - assertThat(groupPermissionDao.countGroups(dbSession, GlobalPermissions.SYSTEM_ADMIN, null)).isEqualTo(1); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "system-admins"); + db.users().insertPermissionOnGroup(group, SYSTEM_ADMIN); + loginAsAdmin(); expectedException.expect(IllegalArgumentException.class); - expectedException.expectMessage("The last system admin group 'system-admins' cannot be deleted"); + expectedException.expectMessage("The last system admin group cannot be deleted"); newRequest() .setParam(PARAM_GROUP_NAME, group.getName()) @@ -189,12 +220,12 @@ public class DeleteActionTest { } @Test - public void can_delete_system_admin_group_if_not_last() throws Exception { - GroupDto funkyAdmins = groupDb.insertGroup(newGroupDto().setName("funky-admins")); - roleDao.insertGroupRole(dbSession, new GroupPermissionDto().setGroupId(funkyAdmins.getId()).setRole(GlobalPermissions.SYSTEM_ADMIN)); - GroupDto boringAdmins = groupDb.insertGroup(newGroupDto().setName("boring-admins")); - roleDao.insertGroupRole(dbSession, new GroupPermissionDto().setGroupId(boringAdmins.getId()).setRole(GlobalPermissions.SYSTEM_ADMIN)); - dbSession.commit(); + public void delete_system_admin_group_if_not_last() throws Exception { + OrganizationDto defaultOrg = defaultOrganizationProvider.getDto(); + GroupDto funkyAdmins = db.users().insertGroup(defaultOrg, "funky-admins"); + db.users().insertPermissionOnGroup(funkyAdmins, SYSTEM_ADMIN); + GroupDto boringAdmins = db.users().insertGroup(defaultOrg, "boring-admins"); + db.users().insertPermissionOnGroup(boringAdmins, SYSTEM_ADMIN); loginAsAdmin(); @@ -202,29 +233,32 @@ public class DeleteActionTest { .setParam(PARAM_GROUP_NAME, boringAdmins.getName()) .execute(); - assertThat(groupPermissionDao.countGroups(dbSession, GlobalPermissions.SYSTEM_ADMIN, null)).isEqualTo(1); + assertThat(db.getDbClient().groupPermissionDao().countGroups(db.getSession(), SYSTEM_ADMIN, null)).isEqualTo(1); } @Test - public void can_delete_last_system_admin_group_if_admin_user_left() throws Exception { - GroupDto lastGroup = groupDb.insertGroup(newGroupDto().setName("last-group")); - roleDao.insertGroupRole(dbSession, new GroupPermissionDto().setGroupId(lastGroup.getId()).setRole(GlobalPermissions.SYSTEM_ADMIN)); - UserDto bigBoss = userDb.insertUser(newUserDto("big.boss", "Big Boss", "big@boss.com")); - dbClient.userPermissionDao().insert(dbSession, new UserPermissionDto(GlobalPermissions.SYSTEM_ADMIN, bigBoss.getId(), null)); - dbSession.commit(); + public void delete_last_system_admin_group_if_admin_user_left() throws Exception { + GroupDto lastGroup = db.users().insertGroup(defaultOrganizationProvider.getDto(), "last-group"); + db.users().insertPermissionOnGroup(lastGroup, SYSTEM_ADMIN); + UserDto bigBoss = db.users().insertUser("big.boss"); + db.users().insertPermissionOnUser(bigBoss, SYSTEM_ADMIN); loginAsAdmin(); - newRequest().setParam(PARAM_GROUP_NAME, lastGroup.getName()).execute(); - assertThat(groupDao.selectById(dbSession, lastGroup.getId())).isNull(); + assertThat(db.users().selectGroupById(lastGroup.getId())).isNull(); } private void loginAsAdmin() { - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + userSession.login("admin").setGlobalPermissions(SYSTEM_ADMIN); } private WsTester.TestRequest newRequest() { return ws.newPostRequest("api/user_groups", "delete"); } + + private GroupWsSupport newGroupWsSupport() { + return new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/GroupWsRefTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/GroupWsRefTest.java new file mode 100644 index 00000000000..2afb8fe4b2c --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/GroupWsRefTest.java @@ -0,0 +1,89 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.server.usergroups.ws; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.server.usergroups.ws.GroupWsRef.fromName; + +public class GroupWsRefTest { + + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void test_ref_by_id() { + GroupWsRef ref = GroupWsRef.fromId(10L); + assertThat(ref.hasId()).isTrue(); + assertThat(ref.getId()).isEqualTo(10L); + assertThat(ref.isAnyone()).isFalse(); + } + + @Test + public void test_ref_by_name() { + GroupWsRef ref = fromName("ORG1", "the-group"); + assertThat(ref.hasId()).isFalse(); + assertThat(ref.getOrganizationKey()).isEqualTo("ORG1"); + assertThat(ref.getName()).isEqualTo("the-group"); + assertThat(ref.isAnyone()).isFalse(); + } + + @Test + public void test_equals_and_hashCode() { + GroupWsRef refId1 = GroupWsRef.fromId(10L); + GroupWsRef refId2 = GroupWsRef.fromId(11L); + assertThat(refId1.equals(refId1)).isTrue(); + assertThat(refId1.equals(GroupWsRef.fromId(10L))).isTrue(); + assertThat(refId1.hashCode()).isEqualTo(GroupWsRef.fromId(10L).hashCode()); + assertThat(refId1.equals(refId2)).isFalse(); + + GroupWsRef refName1 = fromName("ORG1", "the-group"); + GroupWsRef refName2 = fromName("ORG1", "the-group2"); + GroupWsRef refName3 = fromName("ORG2", "the-group2"); + assertThat(refName1.equals(refName1)).isTrue(); + assertThat(refName1.equals(fromName("ORG1", "the-group"))).isTrue(); + assertThat(refName1.hashCode()).isEqualTo(fromName("ORG1", "the-group").hashCode()); + assertThat(refName1.equals(refName2)).isFalse(); + assertThat(refName2.equals(refName3)).isFalse(); + } + + @Test + public void test_toString() { + GroupWsRef refId = GroupWsRef.fromId(10L); + assertThat(refId.toString()).isEqualTo("GroupWsRef{id=10, organizationKey='null', name='null'}"); + } + + @Test + public void reference_anyone_by_its_name() { + GroupWsRef ref = GroupWsRef.fromName("my-org", "Anyone"); + assertThat(ref.getOrganizationKey()).isEqualTo("my-org"); + assertThat(ref.getName()).isEqualTo("Anyone"); + assertThat(ref.isAnyone()).isTrue(); + + // case-insensitive + ref = GroupWsRef.fromName("my-org", "anyone"); + assertThat(ref.getOrganizationKey()).isEqualTo("my-org"); + assertThat(ref.getName()).isEqualTo("anyone"); + assertThat(ref.isAnyone()).isTrue(); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/RemoveUserActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/RemoveUserActionTest.java index cc206a856b0..b2a6d1c9dfa 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/RemoveUserActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/RemoveUserActionTest.java @@ -19,145 +19,136 @@ */ package org.sonar.server.usergroups.ws; -import java.util.Arrays; -import org.apache.commons.lang.StringUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; import org.sonar.core.permission.GlobalPermissions; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.user.GroupDao; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; import org.sonar.db.user.GroupDto; -import org.sonar.db.user.GroupMembershipDao; -import org.sonar.db.user.UserDao; import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDao; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_LOGIN; - +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_LOGIN; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_ORGANIZATION_KEY; public class RemoveUserActionTest { @Rule public DbTester db = DbTester.create(System2.INSTANCE); @Rule - public final UserSessionRule userSession = UserSessionRule.standalone(); + public UserSessionRule userSession = UserSessionRule.standalone(); @Rule - public final ExpectedException expectedException = ExpectedException.none(); + public ExpectedException expectedException = ExpectedException.none(); + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); private WsTester ws; - private GroupDao groupDao; - private UserDao userDao; - private GroupMembershipDao groupMembershipDao; - private UserGroupDao userGroupDao; - private DbSession dbSession; @Before public void setUp() { - dbSession = db.getSession(); - - org.sonar.db.DbClient dbClient = db.getDbClient(); - groupDao = dbClient.groupDao(); - userDao = dbClient.userDao(); - groupMembershipDao = dbClient.groupMembershipDao(); - userGroupDao = dbClient.userGroupDao(); - - ws = new WsTester(new UserGroupsWs(new RemoveUserAction(dbClient, userSession))); + GroupWsSupport groupSupport = new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); + ws = new WsTester(new UserGroupsWs(new RemoveUserAction(db.getDbClient(), userSession, groupSupport))); } @Test - public void remove_user_not_in_group() throws Exception { - GroupDto group = insertGroup("admins"); - UserDto user = insertUser("my-admin"); - dbSession.commit(); + public void does_nothing_if_user_is_not_in_group() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "admins"); + UserDto user = db.users().insertUser("my-admin"); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .isEmpty(); + assertThat(db.users().selectGroupIdsOfUser(user)).isEmpty(); } @Test - public void remove_user_nominal() throws Exception { - GroupDto users = insertGroup("users"); - UserDto user = insertUser("my-admin"); - insertMember(users.getId(), user.getId()); - dbSession.commit(); - - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + public void remove_user_by_group_id() throws Exception { + GroupDto users = db.users().insertGroup(defaultOrganizationProvider.getDto(), "users"); + UserDto user = db.users().insertUser("my-admin"); + db.users().insertMember(users, user); + loginAsAdmin(); newRequest() .setParam("id", users.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .isEmpty(); + assertThat(db.users().selectGroupIdsOfUser(user)).isEmpty(); } @Test - public void remove_user_by_group_name() throws Exception { - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); - GroupDto group = insertGroup("group_name"); - UserDto user = insertUser("user_login"); - insertMember(group.getId(), user.getId()); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .isNotEmpty(); - db.commit(); + public void remove_user_by_group_name_in_default_organization() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "group_name"); + UserDto user = db.users().insertUser("user_login"); + db.users().insertMember(group, user); + loginAsAdmin(); newRequest() .setParam(PARAM_GROUP_NAME, group.getName()) .setParam(PARAM_LOGIN, user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .isEmpty(); + assertThat(db.users().selectGroupIdsOfUser(user)).isEmpty(); } @Test - public void remove_user_only_from_one_group() throws Exception { - GroupDto users = insertGroup("user"); - GroupDto admins = insertGroup("admins"); - UserDto user = insertUser("user"); - insertMember(users.getId(), user.getId()); - insertMember(admins.getId(), user.getId()); - dbSession.commit(); + public void remove_user_by_group_name_in_specific_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, OrganizationTesting.newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, "a_group"); + UserDto user = db.users().insertUser("user_login"); + db.users().insertMember(group, user); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); + newRequest() + .setParam(PARAM_ORGANIZATION_KEY, org.getKey()) + .setParam(PARAM_GROUP_NAME, group.getName()) + .setParam(PARAM_LOGIN, user.getLogin()) + .execute() + .assertNoContent(); + + assertThat(db.users().selectGroupIdsOfUser(user)).isEmpty(); + } + + @Test + public void remove_user_only_from_one_group() throws Exception { + OrganizationDto defaultOrg = defaultOrganizationProvider.getDto(); + GroupDto users = db.users().insertGroup(defaultOrg, "user"); + GroupDto admins = db.users().insertGroup(defaultOrg, "admins"); + UserDto user = db.users().insertUser("user"); + db.users().insertMember(users, user); + db.users().insertMember(admins, user); + + loginAsAdmin(); newRequest() .setParam("id", admins.getId().toString()) .setParam("login", user.getLogin()) .execute() .assertNoContent(); - assertThat(groupMembershipDao.selectGroupsByLogins(dbSession, Arrays.asList(user.getLogin())).get(user.getLogin())) - .containsOnly(users.getName()); + assertThat(db.users().selectGroupIdsOfUser(user)).containsOnly(users.getId()); } @Test - public void unknown_group() throws Exception { - UserDto user = insertUser("my-admin"); - dbSession.commit(); + public void fail_if_unknown_group() throws Exception { + UserDto user = db.users().insertUser("my-admin"); expectedException.expect(NotFoundException.class); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", "42") .setParam("login", user.getLogin()) @@ -165,13 +156,12 @@ public class RemoveUserActionTest { } @Test - public void unknown_user() throws Exception { - GroupDto group = insertGroup("admins"); - dbSession.commit(); + public void fail_if_unknown_user() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "admins"); expectedException.expect(NotFoundException.class); - userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + loginAsAdmin(); newRequest() .setParam("id", group.getId().toString()) .setParam("login", "my-admin") @@ -182,17 +172,8 @@ public class RemoveUserActionTest { return ws.newPostRequest("api/user_groups", "remove_user"); } - private GroupDto insertGroup(String groupName) { - return groupDao.insert(dbSession, new GroupDto() - .setName(groupName) - .setDescription(StringUtils.capitalize(groupName))); - } - - private UserDto insertUser(String login) { - return userDao.insert(dbSession, new UserDto().setLogin(login).setName(login).setActive(true)); + private void loginAsAdmin() { + userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } - private void insertMember(long groupId, long userId) { - userGroupDao.insert(dbSession, new UserGroupDto().setGroupId(groupId).setUserId(userId)); - } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java index b8c65d582db..542a194e5a7 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/SearchActionTest.java @@ -19,27 +19,27 @@ */ package org.sonar.server.usergroups.ws; -import org.apache.commons.lang.StringUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.System2; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; -import org.sonar.db.user.GroupDao; -import org.sonar.db.user.UserGroupDao; -import org.sonar.db.user.UserGroupDto; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; +import org.sonar.db.user.GroupDto; +import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.UnauthorizedException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; +import static org.apache.commons.lang.StringUtils.capitalize; import static org.assertj.core.api.Assertions.assertThat; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; import static org.sonar.db.user.GroupTesting.newGroupDto; - public class SearchActionTest { @Rule @@ -53,19 +53,9 @@ public class SearchActionTest { private WsTester ws; - private GroupDao groupDao; - private UserGroupDao userGroupDao; - private DbSession dbSession; - @Before public void setUp() { - DbClient dbClient = db.getDbClient(); - groupDao = dbClient.groupDao(); - userGroupDao = dbClient.userGroupDao(); - - ws = new WsTester(new UserGroupsWs(new SearchAction(dbClient, userSession))); - - dbSession = dbClient.openSession(false); + ws = new WsTester(new UserGroupsWs(new SearchAction(db.getDbClient(), userSession, newGroupWsSupport()))); } @Test @@ -76,40 +66,49 @@ public class SearchActionTest { @Test public void search_without_parameters() throws Exception { - loginAsSimpleUser(); - insertGroups("users", "admins", "customer1", "customer2", "customer3"); - dbSession.commit(); + insertGroup(db.getDefaultOrganization(), "users", 0); + insertGroup(db.getDefaultOrganization(), "admins", 0); + insertGroup(db.getDefaultOrganization(), "customer1", 0); + insertGroup(db.getDefaultOrganization(), "customer2", 0); + insertGroup(db.getDefaultOrganization(), "customer3", 0); + loginAsSimpleUser(); newRequest().execute().assertJson(getClass(), "five_groups.json"); } @Test public void search_with_members() throws Exception { - loginAsSimpleUser(); - insertGroups("users", "admins", "customer1", "customer2", "customer3"); - insertMembers("users", 5); - insertMembers("admins", 1); - insertMembers("customer2", 4); - dbSession.commit(); + insertGroup(db.getDefaultOrganization(), "users", 5); + insertGroup(db.getDefaultOrganization(), "admins", 1); + insertGroup(db.getDefaultOrganization(), "customer1", 0); + insertGroup(db.getDefaultOrganization(), "customer2", 4); + insertGroup(db.getDefaultOrganization(), "customer3", 0); + loginAsSimpleUser(); newRequest().execute().assertJson(getClass(), "with_members.json"); } @Test public void search_with_query() throws Exception { - loginAsSimpleUser(); - insertGroups("users", "admins", "customer%_%/1", "customer%_%/2", "customer%_%/3"); - dbSession.commit(); + insertGroup(db.getDefaultOrganization(), "users", 0); + insertGroup(db.getDefaultOrganization(), "admins", 0); + insertGroup(db.getDefaultOrganization(), "customer%_%/1", 0); + insertGroup(db.getDefaultOrganization(), "customer%_%/2", 0); + insertGroup(db.getDefaultOrganization(), "customer%_%/3", 0); + loginAsSimpleUser(); newRequest().setParam(Param.TEXT_QUERY, "tomer%_%/").execute().assertJson(getClass(), "customers.json"); } @Test public void search_with_paging() throws Exception { - loginAsSimpleUser(); - insertGroups("users", "admins", "customer1", "customer2", "customer3"); - dbSession.commit(); + insertGroup(db.getDefaultOrganization(), "users", 0); + insertGroup(db.getDefaultOrganization(), "admins", 0); + insertGroup(db.getDefaultOrganization(), "customer1", 0); + insertGroup(db.getDefaultOrganization(), "customer2", 0); + insertGroup(db.getDefaultOrganization(), "customer3", 0); + loginAsSimpleUser(); newRequest() .setParam(Param.PAGE_SIZE, "3").execute().assertJson(getClass(), "page_1.json"); newRequest() @@ -120,10 +119,9 @@ public class SearchActionTest { @Test public void search_with_fields() throws Exception { - loginAsSimpleUser(); - insertGroups("sonar-users"); - dbSession.commit(); + insertGroup(db.getDefaultOrganization(), "sonar-users", 0); + loginAsSimpleUser(); assertThat(newRequest().execute().outputAsString()) .contains("id") .contains("name") @@ -156,7 +154,23 @@ public class SearchActionTest { } @Test - public void fail_when_not_logged() throws Exception { + public void search_in_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + GroupDto group = db.users().insertGroup(org, "users"); + // the group in default org is not returned + db.users().insertGroup(db.getDefaultOrganization(), "users"); + + loginAsSimpleUser(); + newRequest() + .setParam("organization", org.getKey()) + .execute() + .assertJson( + "{\"total\":1,\"p\":1,\"ps\":100," + + "\"groups\":[{\"id\":\"" + group.getId() + "\",\"name\":\"users\"}]}\n"); + } + + @Test + public void fail_when_not_logged_in() throws Exception { userSession.anonymous(); expectedException.expect(UnauthorizedException.class); @@ -167,18 +181,12 @@ public class SearchActionTest { return ws.newGetRequest("api/user_groups", "search"); } - private void insertGroups(String... groupNames) { - for (String groupName : groupNames) { - groupDao.insert(dbSession, newGroupDto() - .setName(groupName) - .setDescription(StringUtils.capitalize(groupName))); - } - } - - private void insertMembers(String groupName, int count) { - long groupId = groupDao.selectOrFailByName(dbSession, groupName).getId(); - for (int i = 0; i < count; i++) { - userGroupDao.insert(dbSession, new UserGroupDto().setGroupId(groupId).setUserId((long) i + 1)); + private void insertGroup(OrganizationDto org, String name, int numberOfMembers) { + GroupDto group = newGroupDto().setName(name).setDescription(capitalize(name)).setOrganizationUuid(org.getUuid()); + db.users().insertGroup(group); + for (int i = 0; i < numberOfMembers; i++) { + UserDto user = db.users().insertUser(); + db.users().insertMember(group, user); } } @@ -186,4 +194,8 @@ public class SearchActionTest { userSession.login("user"); } + private GroupWsSupport newGroupWsSupport() { + return new GroupWsSupport(db.getDbClient(), DefaultOrganizationProviderRule.create(db)); + } + } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UpdateActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UpdateActionTest.java index df57395d868..ba6b7a57339 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UpdateActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UpdateActionTest.java @@ -19,7 +19,6 @@ */ package org.sonar.server.usergroups.ws; -import java.net.HttpURLConnection; import org.apache.commons.lang.StringUtils; import org.junit.Before; import org.junit.Rule; @@ -27,16 +26,16 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.sonar.api.utils.System2; 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.user.GroupDao; +import org.sonar.db.organization.OrganizationDto; +import org.sonar.db.organization.OrganizationTesting; import org.sonar.db.user.GroupDto; -import org.sonar.db.user.UserGroupDao; -import org.sonar.db.user.UserGroupDto; +import org.sonar.db.user.UserDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; import org.sonar.server.exceptions.ServerException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.platform.PersistentSettings; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; @@ -47,42 +46,40 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.db.organization.OrganizationTesting.newOrganizationDto; public class UpdateActionTest { - static final String DEFAULT_GROUP_NAME_KEY = "sonar.defaultGroup"; - static final String DEFAULT_GROUP_NAME_VALUE = "DEFAULT_GROUP_NAME_VALUE"; + private static final String DEFAULT_GROUP_NAME_KEY = "sonar.defaultGroup"; + private static final String DEFAULT_GROUP_NAME_VALUE = "DEFAULT_GROUP_NAME_VALUE"; @Rule public DbTester db = DbTester.create(System2.INSTANCE); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - @Rule public ExpectedException expectedException = ExpectedException.none(); - DbClient dbClient = db.getDbClient(); - DbSession dbSession = db.getSession(); - GroupDao groupDao = dbClient.groupDao(); - UserGroupDao userGroupDao = dbClient.userGroupDao(); - PersistentSettings settings = mock(PersistentSettings.class); - WsTester ws = new WsTester(new UserGroupsWs(new UpdateAction(dbClient, userSession, new UserGroupUpdater(dbClient), settings))); + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); + private PersistentSettings settings = mock(PersistentSettings.class); + private WsTester ws = new WsTester(new UserGroupsWs(new UpdateAction(db.getDbClient(), userSession, new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider), settings, defaultOrganizationProvider))); @Before public void setUp() throws Exception { + GroupWsSupport groupSupport = new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); + ws = new WsTester(new UserGroupsWs(new UpdateAction(db.getDbClient(), userSession, groupSupport, settings, defaultOrganizationProvider))); when(settings.getString(DEFAULT_GROUP_NAME_KEY)).thenReturn(DEFAULT_GROUP_NAME_VALUE); } @Test - public void update_nominal() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - userGroupDao.insert(dbSession, new UserGroupDto().setGroupId(existingGroup.getId()).setUserId(42L)); - - dbSession.commit(); + public void update_both_name_and_description() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "Initial Name"); + UserDto user = db.users().insertUser(); + db.users().insertMember(group, user); loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "new-name") .setParam("description", "New Description") .execute().assertJson("{" + @@ -96,17 +93,16 @@ public class UpdateActionTest { @Test public void update_only_name() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "Initial Name"); loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "new-name") .execute().assertJson("{" + " \"group\": {" + " \"name\": \"new-name\"," + - " \"description\": \"Old Description\"," + + " \"description\": \"" + group.getDescription() + "\"," + " \"membersCount\": 0" + " }" + "}"); @@ -114,16 +110,15 @@ public class UpdateActionTest { @Test public void update_only_description() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "Initial Name"); loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("description", "New Description") .execute().assertJson("{" + " \"group\": {" + - " \"name\": \"old-name\"," + + " \"name\": \"" + group.getName() + "\"," + " \"description\": \"New Description\"," + " \"membersCount\": 0" + " }" + @@ -132,12 +127,11 @@ public class UpdateActionTest { @Test public void update_default_group_name_also_update_default_group_property() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName(DEFAULT_GROUP_NAME_VALUE).setDescription("Default group name")); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), DEFAULT_GROUP_NAME_VALUE); loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "new-name") .execute(); @@ -147,12 +141,27 @@ public class UpdateActionTest { @Test public void update_default_group_name_does_not_update_default_group_setting_when_null() throws Exception { when(settings.getString(DEFAULT_GROUP_NAME_KEY)).thenReturn(null); - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName(DEFAULT_GROUP_NAME_VALUE).setDescription("Default group name")); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), DEFAULT_GROUP_NAME_VALUE); + + loginAsAdmin(); + newRequest() + .setParam("id", group.getId().toString()) + .setParam("name", "new-name") + .execute(); + + verify(settings, never()).saveProperty(any(DbSession.class), eq(DEFAULT_GROUP_NAME_KEY), eq("new-name")); + } + + @Test + public void do_not_update_default_group_of_default_organization_if_updating_group_on_non_default_organization() throws Exception { + OrganizationDto org = OrganizationTesting.insert(db, newOrganizationDto()); + when(settings.getString(DEFAULT_GROUP_NAME_KEY)).thenReturn(DEFAULT_GROUP_NAME_VALUE); + GroupDto groupInDefaultOrg = db.users().insertGroup(defaultOrganizationProvider.getDto(), DEFAULT_GROUP_NAME_VALUE); + GroupDto group = db.users().insertGroup(org, DEFAULT_GROUP_NAME_VALUE); loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "new-name") .execute(); @@ -161,9 +170,10 @@ public class UpdateActionTest { @Test public void require_admin_permission() throws Exception { + userSession.login("not-admin"); + expectedException.expect(ForbiddenException.class); - userSession.login("not-admin"); newRequest() .setParam("id", "42") .setParam("name", "some-product-bu") @@ -172,85 +182,86 @@ public class UpdateActionTest { } @Test - public void name_too_short() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + public void fail_if_name_is_too_short() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a name"); + loginAsAdmin(); expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Group name cannot be empty"); - loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "") .execute(); } @Test - public void name_too_long() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + public void fail_if_name_is_too_long() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a name"); + loginAsAdmin(); expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Group name cannot be longer than 255 characters"); - loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", StringUtils.repeat("a", 255 + 1)) .execute(); } @Test - public void forbidden_name() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + public void fail_if_new_name_is_anyone() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a name"); + loginAsAdmin(); expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Anyone group cannot be used"); - loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "AnYoNe") .execute(); } @Test - public void non_unique_name() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - String groupName = "conflicting-name"; - groupDao.insert(dbSession, new GroupDto() - .setName(groupName)); - dbSession.commit(); + public void fail_to_update_if_name_already_exists() throws Exception { + OrganizationDto defaultOrg = defaultOrganizationProvider.getDto(); + GroupDto groupToBeRenamed = db.users().insertGroup(defaultOrg, "a name"); + String newName = "new-name"; + db.users().insertGroup(defaultOrg, newName); + loginAsAdmin(); expectedException.expect(ServerException.class); - expectedException.expectMessage("already taken"); + expectedException.expectMessage("Group 'new-name' already exists"); - loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) - .setParam("name", groupName) - .execute().assertStatus(HttpURLConnection.HTTP_CONFLICT); + .setParam("id", groupToBeRenamed.getId().toString()) + .setParam("name", newName) + .execute(); } @Test - public void description_too_long() throws Exception { - GroupDto existingGroup = groupDao.insert(dbSession, new GroupDto().setName("old-name").setDescription("Old Description")); - dbSession.commit(); + public void fail_if_description_is_too_long() throws Exception { + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a name"); + loginAsAdmin(); expectedException.expect(IllegalArgumentException.class); + expectedException.expectMessage("Description cannot be longer than 200 characters"); - loginAsAdmin(); newRequest() - .setParam("id", existingGroup.getId().toString()) + .setParam("id", group.getId().toString()) .setParam("name", "long-group-description-is-looooooooooooong") - .setParam("description", StringUtils.repeat("a", 200 + 1)) + .setParam("description", StringUtils.repeat("a", 201)) .execute(); } @Test - public void unknown_group() throws Exception { + public void fail_if_unknown_group() throws Exception { + loginAsAdmin(); + expectedException.expect(NotFoundException.class); + expectedException.expectMessage("Could not find a user group with id '42'."); - loginAsAdmin(); newRequest() .setParam("id", "42") .execute(); @@ -263,6 +274,4 @@ public class UpdateActionTest { private void loginAsAdmin() { userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } - - } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsModuleTest.java index e533bb7f61d..44c4a8dac0b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsModuleTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsModuleTest.java @@ -29,6 +29,6 @@ public class UserGroupsModuleTest { public void verify_count_of_added_components() { ComponentContainer container = new ComponentContainer(); new UserGroupsModule().configure(container); - assertThat(container.size()).isEqualTo(12); + assertThat(container.size()).isEqualTo(11); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsWsTest.java index 2e8b7a6755e..476c532a510 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UserGroupsWsTest.java @@ -40,9 +40,10 @@ public class UserGroupsWsTest { @Before public void setUp() { + GroupWsSupport wsSupport = mock(GroupWsSupport.class); WsTester tester = new WsTester(new UserGroupsWs( - new SearchAction(mock(DbClient.class), mock(UserSession.class)), - new CreateAction(mock(DbClient.class), mock(UserSession.class), mock(UserGroupUpdater.class)))); + new SearchAction(mock(DbClient.class), mock(UserSession.class), wsSupport), + new CreateAction(mock(DbClient.class), mock(UserSession.class), wsSupport))); controller = tester.controller("api/user_groups"); } @@ -59,7 +60,7 @@ public class UserGroupsWsTest { WebService.Action action = controller.action("search"); assertThat(action).isNotNull(); assertThat(action.responseExampleAsString()).isNotEmpty(); - assertThat(action.params()).hasSize(4); + assertThat(action.params()).hasSize(5); } @Test @@ -68,6 +69,6 @@ public class UserGroupsWsTest { assertThat(action).isNotNull(); assertThat(action.isPost()).isTrue(); assertThat(action.responseExampleAsString()).isNotEmpty(); - assertThat(action.params()).hasSize(2); + assertThat(action.params()).hasSize(3); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java index 4c1b09f0697..af0c949661b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/usergroups/ws/UsersActionTest.java @@ -26,21 +26,19 @@ 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.core.permission.GlobalPermissions; -import org.sonar.db.DbClient; -import org.sonar.db.DbSession; import org.sonar.db.DbTester; import org.sonar.db.user.GroupDto; import org.sonar.db.user.UserDto; -import org.sonar.db.user.UserGroupDto; import org.sonar.server.exceptions.ForbiddenException; import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.organization.DefaultOrganizationProviderRule; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.ws.WsTester; import org.sonar.server.ws.WsTester.TestRequest; import static org.assertj.core.api.Assertions.assertThat; -import static org.sonar.server.usergroups.ws.UserGroupsWsParameters.PARAM_GROUP_NAME; - +import static org.sonar.db.user.UserTesting.newUserDto; +import static org.sonar.server.usergroups.ws.GroupWsSupport.PARAM_GROUP_NAME; public class UsersActionTest { @@ -48,34 +46,30 @@ public class UsersActionTest { public DbTester db = DbTester.create(System2.INSTANCE); @Rule public UserSessionRule userSession = UserSessionRule.standalone(); - - WsTester wsTester; - DbClient dbClient; - DbSession dbSession; + private DefaultOrganizationProviderRule defaultOrganizationProvider = DefaultOrganizationProviderRule.create(db); + private WsTester wsTester; @Before public void setUp() { - dbClient = db.getDbClient(); - dbSession = db.getSession(); - + GroupWsSupport groupSupport = new GroupWsSupport(db.getDbClient(), defaultOrganizationProvider); wsTester = new WsTester(new UserGroupsWs( new UsersAction( - dbClient, - new UserGroupFinder(dbClient), - userSession))); + db.getDbClient(), + userSession, + groupSupport))); userSession.login("admin").setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); } @Test(expected = NotFoundException.class) - public void fail_on_unknown_user() throws Exception { + public void fail_if_unknown_user() throws Exception { newUsersRequest() .setParam("id", "42") .setParam("login", "john").execute(); } @Test(expected = ForbiddenException.class) - public void fail_on_missing_permission() throws Exception { + public void fail_if_missing_permission() throws Exception { userSession.login("not-admin"); newUsersRequest() .setParam("id", "42") @@ -84,8 +78,7 @@ public class UsersActionTest { @Test public void empty_users() throws Exception { - GroupDto group = insertGroup(); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); newUsersRequest() .setParam("login", "john") @@ -96,11 +89,10 @@ public class UsersActionTest { @Test public void all_users() throws Exception { - GroupDto group = insertGroup(); - UserDto groupUser = insertUser("ada", "Ada Lovelace"); - insertUser("grace", "Grace Hopper"); - addUserToGroup(groupUser, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + db.users().insertMember(group, user1); + db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); newUsersRequest() .setParam("id", group.getId().toString()) @@ -111,12 +103,11 @@ public class UsersActionTest { @Test public void all_users_by_group_name() throws Exception { - GroupDto group = insertGroup(); - UserDto adaLovelace = insertUser("ada", "Ada Lovelace"); - UserDto graceHopper = insertUser("grace", "Grace Hopper"); - addUserToGroup(adaLovelace, group); - addUserToGroup(graceHopper, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto adaLovelace = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + UserDto graceHopper = db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); + db.users().insertMember(group, adaLovelace); + db.users().insertMember(group, graceHopper); String response = newUsersRequest() .setParam(PARAM_GROUP_NAME, group.getName()) @@ -127,11 +118,10 @@ public class UsersActionTest { @Test public void selected_users() throws Exception { - GroupDto group = insertGroup(); - UserDto groupUser = insertUser("ada", "Ada Lovelace"); - insertUser("grace", "Grace Hopper"); - addUserToGroup(groupUser, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); + db.users().insertMember(group, user1); newUsersRequest() .setParam("id", group.getId().toString()) @@ -147,11 +137,10 @@ public class UsersActionTest { @Test public void deselected_users() throws Exception { - GroupDto group = insertGroup(); - UserDto groupUser = insertUser("ada", "Ada Lovelace"); - insertUser("grace", "Grace Hopper"); - addUserToGroup(groupUser, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); + db.users().insertMember(group, user1); newUsersRequest() .setParam("id", group.getId().toString()) @@ -162,11 +151,10 @@ public class UsersActionTest { @Test public void paging() throws Exception { - GroupDto group = insertGroup(); - UserDto groupUser = insertUser("ada", "Ada Lovelace"); - insertUser("grace", "Grace Hopper"); - addUserToGroup(groupUser, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); + db.users().insertMember(group, user1); newUsersRequest() .setParam("id", group.getId().toString()) @@ -186,11 +174,10 @@ public class UsersActionTest { @Test public void filtering() throws Exception { - GroupDto group = insertGroup(); - UserDto groupUser = insertUser("ada", "Ada Lovelace"); - insertUser("grace", "Grace Hopper"); - addUserToGroup(groupUser, group); - dbSession.commit(); + GroupDto group = db.users().insertGroup(defaultOrganizationProvider.getDto(), "a group"); + UserDto user1 = db.users().insertUser(newUserDto().setLogin("ada").setName("Ada Lovelace")); + db.users().insertUser(newUserDto().setLogin("grace").setName("Grace Hopper")); + db.users().insertMember(group, user1); newUsersRequest() .setParam("id", group.getId().toString()) @@ -210,16 +197,4 @@ public class UsersActionTest { return wsTester.newGetRequest("api/user_groups", "users"); } - private GroupDto insertGroup() { - return dbClient.groupDao().insert(dbSession, new GroupDto() - .setName("sonar-users")); - } - - private UserDto insertUser(String login, String name) { - return dbClient.userDao().insert(dbSession, new UserDto().setLogin(login).setName(name)); - } - - private void addUserToGroup(UserDto user, GroupDto usersGroup) { - dbClient.userGroupDao().insert(dbSession, new UserGroupDto().setUserId(user.getId()).setGroupId(usersGroup.getId())); - } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/associate_default_groups_when_reactivating_user.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/associate_default_groups_when_reactivating_user.xml index d2470c724ab..eb584fdc8a0 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/associate_default_groups_when_reactivating_user.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/associate_default_groups_when_reactivating_user.xml @@ -18,7 +18,8 @@ name="sonar-devs" description="Sonar Devs" created_at="2014-09-08" - updated_at="2014-09-08"/> + updated_at="2014-09-08" + organization_uuid="org1"/> <groups_users user_id="101" group_id="1"/> diff --git a/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/not_associate_default_group_when_updating_user_if_already_existing.xml b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/not_associate_default_group_when_updating_user_if_already_existing.xml index ea65c7abcfd..95ec8776256 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/not_associate_default_group_when_updating_user_if_already_existing.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/user/UserUpdaterTest/not_associate_default_group_when_updating_user_if_already_existing.xml @@ -18,7 +18,8 @@ name="sonar-users" description="Sonar Users" created_at="2014-09-08" - updated_at="2014-09-08"/> + updated_at="2014-09-08" + organization_uuid="org1"/> <groups_users user_id="101" group_id="1"/> diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1403_add_root_column_on_table_users.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1404_add_root_column_on_table_users.rb index 154adcc8b60..154adcc8b60 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1403_add_root_column_on_table_users.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1404_add_root_column_on_table_users.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1404_populate_root_column_on_table_users.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1405_populate_root_column_on_table_users.rb index d15774555e1..d15774555e1 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1404_populate_root_column_on_table_users.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1405_populate_root_column_on_table_users.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1405_make_root_column_not_null_on_table_users.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1406_make_root_column_not_null_on_table_users.rb index 97d9dbea5c7..97d9dbea5c7 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1405_make_root_column_not_null_on_table_users.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1406_make_root_column_not_null_on_table_users.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1406_populate_organization_uuid_of_groups.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1407_populate_organization_uuid_of_groups.rb index 3482e679978..3482e679978 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1406_populate_organization_uuid_of_groups.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1407_populate_organization_uuid_of_groups.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1407_make_organization_uuid_not_null_on_groups.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1408_make_organization_uuid_not_null_on_groups.rb index d553d1c5614..d553d1c5614 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1407_make_organization_uuid_not_null_on_groups.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1408_make_organization_uuid_not_null_on_groups.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1408_add_organization_uuid_to_user_roles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1409_add_organization_uuid_to_user_roles.rb index 977524cdcb8..977524cdcb8 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1408_add_organization_uuid_to_user_roles.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1409_add_organization_uuid_to_user_roles.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1409_populate_organization_uuid_of_user_roles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1410_populate_organization_uuid_of_user_roles.rb index f26b71b0d0a..f26b71b0d0a 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1409_populate_organization_uuid_of_user_roles.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1410_populate_organization_uuid_of_user_roles.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1410_make_organization_uuid_not_null_on_user_roles.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1411_make_organization_uuid_not_null_on_user_roles.rb index ecf2e345f7d..ecf2e345f7d 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1410_make_organization_uuid_not_null_on_user_roles.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1411_make_organization_uuid_not_null_on_user_roles.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1411_add_organization_uuid_to_permission_templates.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1412_add_organization_uuid_to_permission_templates.rb index 01d94e19572..01d94e19572 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1411_add_organization_uuid_to_permission_templates.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1412_add_organization_uuid_to_permission_templates.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1412_populate_organization_uuid_of_permission_templates.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1413_populate_organization_uuid_of_permission_templates.rb index d855a08cfa0..d855a08cfa0 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1412_populate_organization_uuid_of_permission_templates.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1413_populate_organization_uuid_of_permission_templates.rb diff --git a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1413_make_organization_uuid_not_null_on_permission_templates.rb b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1414_make_organization_uuid_not_null_on_permission_templates.rb index 8258665b4a1..8258665b4a1 100644 --- a/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1413_make_organization_uuid_not_null_on_permission_templates.rb +++ b/server/sonar-web/src/main/webapp/WEB-INF/db/migrate/1414_make_organization_uuid_not_null_on_permission_templates.rb |