Skip to content

Commit

Permalink
SONAR-6470 New Java WS to show a user's groups
Browse files Browse the repository at this point in the history
  • Loading branch information
jblievremont committed May 7, 2015
1 parent f7c5f42 commit 912e988
Show file tree
Hide file tree
Showing 16 changed files with 476 additions and 16 deletions.
Expand Up @@ -34,6 +34,7 @@
import org.sonar.core.template.LoadedTemplateDao;
import org.sonar.core.user.AuthorDao;
import org.sonar.core.user.AuthorizationDao;
import org.sonar.core.user.GroupMembershipDao;
import org.sonar.server.activity.db.ActivityDao;
import org.sonar.server.component.db.ComponentDao;
import org.sonar.server.component.db.ComponentIndexDao;
Expand Down Expand Up @@ -85,6 +86,7 @@ public class DbClient implements ServerComponent {
private final UserDao userDao;
private final GroupDao groupDao;
private final UserGroupDao userGroupDao;
private final GroupMembershipDao groupMembershipDao;
private final IssueDao issueDao;
private final IssueFilterDao issueFilterDao;
private final IssueChangeDao issueChangeDao;
Expand Down Expand Up @@ -124,6 +126,7 @@ public DbClient(Database db, MyBatis myBatis, DaoComponent... daoComponents) {
userDao = getDao(map, UserDao.class);
groupDao = getDao(map, GroupDao.class);
userGroupDao = getDao(map, UserGroupDao.class);
groupMembershipDao = getDao(map, GroupMembershipDao.class);
issueDao = getDao(map, IssueDao.class);
issueFilterDao = getDao(map, IssueFilterDao.class);
issueChangeDao = getDao(map, IssueChangeDao.class);
Expand Down Expand Up @@ -224,6 +227,10 @@ public UserGroupDao userGroupDao() {
return userGroupDao;
}

public GroupMembershipDao groupMembershipDao() {
return groupMembershipDao;
}

public ActionPlanDao actionPlanDao() {
return actionPlanDao;
}
Expand Down
Expand Up @@ -762,6 +762,7 @@ void startLevel4Components(ComponentContainer pico) {
pico.addSingleton(org.sonar.server.user.ws.ChangePasswordAction.class);
pico.addSingleton(org.sonar.server.user.ws.CurrentUserAction.class);
pico.addSingleton(org.sonar.server.user.ws.SearchAction.class);
pico.addSingleton(org.sonar.server.user.ws.GroupsAction.class);
pico.addSingleton(org.sonar.server.issue.ws.AuthorsAction.class);
pico.addSingleton(FavoritesWs.class);
pico.addSingleton(UserPropertiesWs.class);
Expand Down
@@ -0,0 +1,139 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
package org.sonar.server.user.ws;

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.server.ws.WebService.Param;
import org.sonar.api.utils.Paging;
import org.sonar.api.utils.text.JsonWriter;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.user.GroupMembershipDto;
import org.sonar.core.user.GroupMembershipQuery;
import org.sonar.core.user.UserDto;
import org.sonar.server.db.DbClient;

import javax.annotation.Nullable;

import java.util.List;

public class GroupsAction implements BaseUsersWsAction {

private static final String PARAM_LOGIN = "login";
private static final String PARAM_SELECTED = "selected";
private static final String PARAM_QUERY = "q";

private static final String SELECTION_ALL = "all";
private static final String SELECTION_SELECTED = "selected";
private static final String SELECTION_DESELECTED = "deselected";

private final DbClient dbClient;

public GroupsAction(DbClient dbClient) {
this.dbClient = dbClient;
}

@Override
public void define(NewController context) {
NewAction action = context.createAction("groups")
.setDescription("List the groups a user belongs to.")
.setHandler(this)
.setResponseExample(getClass().getResource("example-groups.json"))
.setSince("5.2");

action.createParam(PARAM_LOGIN)
.setDescription("A user login")
.setExampleValue("admin")
.setRequired(true);

action.createParam(PARAM_SELECTED)
.setDescription("If specified, only show groups the user is member of (selected) or not (deselected).")
.setPossibleValues(SELECTION_SELECTED, SELECTION_DESELECTED, SELECTION_ALL)
.setDefaultValue(SELECTION_ALL);

action.createParam(PARAM_QUERY)
.setDescription("If specified, only show groups whose name contains the query.")
.setExampleValue("user");

action.addPagingParams(25);
}

@Override
public void handle(Request request, Response response) throws Exception {
String login = request.mandatoryParam(PARAM_LOGIN);
int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE);
int page = request.mandatoryParamAsInt(Param.PAGE);
String queryString = request.param(PARAM_QUERY);
String selected = request.param(PARAM_SELECTED);

GroupMembershipQuery query = GroupMembershipQuery.builder()
.login(login)
.groupSearch(queryString)
.membership(getMembership(selected))
.pageIndex(page)
.pageSize(pageSize)
.build();

DbSession session = dbClient.openSession(false);
try {
UserDto user = dbClient.userDao().selectByLogin(session, login);
int total = dbClient.groupMembershipDao().countGroups(session, query, user.getId());
Paging paging = Paging.create(pageSize, page, total);
List<GroupMembershipDto> groups = dbClient.groupMembershipDao().selectGroups(session, query, user.getId(), paging.offset(), pageSize);

JsonWriter json = response.newJsonWriter().beginObject();
writeGroups(json, groups);
writePaging(json, paging);
json.endObject().close();
} finally {
session.close();
}
}

private void writeGroups(JsonWriter json, List<GroupMembershipDto> groups) {
json.name("groups").beginArray();
for (GroupMembershipDto group : groups) {
json.beginObject()
.prop("name", group.getName())
.prop("description", group.getDescription())
.prop("selected", group.getUserId() != null)
.endObject();
}
json.endArray();
}

private void writePaging(JsonWriter json, Paging paging) {
json.prop("p", paging.pageIndex())
.prop("ps", paging.pageSize())
.prop("total", paging.total());
}

private String getMembership(@Nullable String selected) {
String membership = GroupMembershipQuery.ANY;
if (SELECTION_SELECTED.equals(selected)) {
membership = GroupMembershipQuery.IN;
} else if (SELECTION_DESELECTED.equals(selected)) {
membership = GroupMembershipQuery.OUT;
}
return membership;
}
}
@@ -0,0 +1,9 @@
{
"p": 1,
"ps": 25,
"total": 2,
"groups": [
{"name": "sonar-admins", "description": "Sonar Admins", "selected": false},
{"name": "sonar-users", "description": "Sonar Users", "selected": true}
]
}
@@ -0,0 +1,199 @@
/*
* SonarQube, open source software quality management tool.
* Copyright (C) 2008-2014 SonarSource
* mailto:contact AT sonarsource DOT com
*
* SonarQube is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* SonarQube is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.user.ws;

import org.junit.After;
import org.junit.Before;
import org.junit.ClassRule;
import org.junit.Test;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.System2;
import org.sonar.core.persistence.DbSession;
import org.sonar.core.persistence.DbTester;
import org.sonar.core.user.GroupDto;
import org.sonar.core.user.GroupMembershipDao;
import org.sonar.core.user.UserDto;
import org.sonar.core.user.UserGroupDto;
import org.sonar.server.db.DbClient;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.user.db.GroupDao;
import org.sonar.server.user.db.UserDao;
import org.sonar.server.user.db.UserGroupDao;
import org.sonar.server.ws.WsTester;

public class GroupsActionTest {

@ClassRule
public static final DbTester dbTester = new DbTester();

WebService.Controller controller;

WsTester tester;

DbClient dbClient;

DbSession session;

@Before
public void setUp() throws Exception {
dbTester.truncateTables();

System2 system2 = new System2();
UserDao userDao = new UserDao(dbTester.myBatis(), system2);
GroupDao groupDao = new GroupDao(system2);
UserGroupDao userGroupDao = new UserGroupDao();
GroupMembershipDao groupMembershipDao = new GroupMembershipDao(dbTester.myBatis());

dbClient = new DbClient(dbTester.database(), dbTester.myBatis(), userDao, groupDao, userGroupDao, groupMembershipDao);
session = dbClient.openSession(false);
session.commit();

tester = new WsTester(new UsersWs(new GroupsAction(dbClient)));
controller = tester.controller("api/users");

}

@After
public void tearDown() throws Exception {
session.close();
}

@Test(expected = NotFoundException.class)
public void fail_on_unknown_user() throws Exception {
tester.newGetRequest("api/users", "groups")
.setParam("login", "john").execute();
}

@Test
public void empty_groups() throws Exception {
createUser();
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.execute()
.assertJson(getClass(), "empty.json");
}

@Test
public void all_groups() throws Exception {
UserDto user = createUser();
GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
createGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.execute()
.assertJson(getClass(), "all.json");
}

@Test
public void selected_groups() throws Exception {
UserDto user = createUser();
GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
createGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("selected", "selected")
.execute()
.assertJson(getClass(), "selected.json");
}

@Test
public void deselected_groups() throws Exception {
UserDto user = createUser();
GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
createGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("selected", "deselected")
.execute()
.assertJson(getClass(), "deselected.json");
}

private UserDto createUser() {
return dbClient.userDao().insert(session, new UserDto()
.setActive(true)
.setEmail("john@email.com")
.setLogin("john")
.setName("John")
.setScmAccounts("jn"));
}

@Test
public void paging() throws Exception {
UserDto user = createUser();
GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
createGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("ps", "1")
.execute()
.assertJson(getClass(), "all_page1.json");

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("ps", "1")
.setParam("p", "2")
.execute()
.assertJson(getClass(), "all_page2.json");
}

@Test
public void filtering() throws Exception {
UserDto user = createUser();
GroupDto usersGroup = createGroup("sonar-users", "Sonar Users");
createGroup("sonar-admins", "Sonar Admins");
addUserToGroup(user, usersGroup);
session.commit();

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("q", "users")
.execute()
.assertJson(getClass(), "all_users.json");

tester.newGetRequest("api/users", "groups")
.setParam("login", "john")
.setParam("q", "admin")
.execute()
.assertJson(getClass(), "all_admin.json");
}

private GroupDto createGroup(String name, String description) {
return dbClient.groupDao().insert(session, new GroupDto().setName(name).setDescription(description));
}

private void addUserToGroup(UserDto user, GroupDto usersGroup) {
dbClient.userGroupDao().insert(session, new UserGroupDto().setUserId(user.getId()).setGroupId(usersGroup.getId()));
}
}

0 comments on commit 912e988

Please sign in to comment.