Skip to content
Snippets Groups Projects
Commit b9d62a20 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added logic for generic search functionality

parent 18d45bca
No related branches found
No related tags found
No related merge requests found
Showing
with 456 additions and 2 deletions
......@@ -24,7 +24,7 @@ public class GroupsTabResponseBuilder {
private GroupsService groupsService;
@Autowired
private GroupsTreeBuilder groupsTreeBuilder;
private GroupsTreeBuilder groupsListBuilder;
public GroupsTabResponse getGroupsTab(GroupsRequest request) {
......@@ -37,7 +37,7 @@ public class GroupsTabResponseBuilder {
Permission currentNodePermissions = permissionsService.getUserPermissionForGroup(group, session.getUserId());
response.setPermission(currentNodePermissions);
response.setGroupsPanel(groupsTreeBuilder.listSubGroups(group, request, session.getUserId()));
response.setGroupsPanel(groupsListBuilder.listSubGroups(group, request, session.getUserId()));
return response;
}
......
package it.inaf.ia2.gms.controller;
import it.inaf.ia2.gms.authn.SessionData;
import it.inaf.ia2.gms.model.response.PaginatedData;
import it.inaf.ia2.gms.model.response.SearchResponseItem;
import it.inaf.ia2.gms.model.response.UserSearchResponse;
import it.inaf.ia2.gms.service.SearchService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class SearchController {
@Autowired
private SessionData sessionData;
@Autowired
private SearchService searchService;
@GetMapping(value = "/search", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<PaginatedData<SearchResponseItem>> getSearchResults(@RequestParam("query") String query,
@RequestParam("page") int page, @RequestParam("pageSize") int pageSize) {
PaginatedData<SearchResponseItem> response = searchService.search(query, sessionData.getUserId(), page, pageSize);
return ResponseEntity.ok(response);
}
@GetMapping(value = "/search/user/{userId}", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public ResponseEntity<UserSearchResponse> getSearchResultUser(@PathVariable("userId") String userId) {
UserSearchResponse response = searchService.getUserSearchResult(sessionData.getUserId(), userId);
return ResponseEntity.ok(response);
}
}
package it.inaf.ia2.gms.model.response;
public class SearchResponseItem {
private SearchResponseType type;
private String label;
private String id;
public SearchResponseType getType() {
return type;
}
public void setType(SearchResponseType type) {
this.type = type;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
}
package it.inaf.ia2.gms.model.response;
public enum SearchResponseType {
GROUP,
USER
}
package it.inaf.ia2.gms.model.response;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import java.util.List;
public class UserSearchResponse {
private List<GroupEntity> groups;
private List<PermissionEntity> permissions;
public List<GroupEntity> getGroups() {
return groups;
}
public void setGroups(List<GroupEntity> groups) {
this.groups = groups;
}
public List<PermissionEntity> getPermissions() {
return permissions;
}
public void setPermissions(List<PermissionEntity> permissions) {
this.permissions = permissions;
}
}
......@@ -299,4 +299,17 @@ public class GroupsDAO {
return breadcrumbs;
});
}
public List<GroupEntity> searchGroups(String searchText) {
String sql = "SELECT id, name, path from gms_group WHERE name ILIKE ?";
return jdbcTemplate.query(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "%" + searchText + "%");
return ps;
}, resultSet -> {
return getGroupsFromResultSet(resultSet);
});
}
}
......@@ -160,4 +160,8 @@ public class GroupsService {
}
return null;
}
public List<GroupEntity> searchGroups(String searchText) {
return groupsDAO.searchGroups(searchText);
}
}
......@@ -16,6 +16,9 @@ import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
/**
* Returns to the user only the groups he or she is allowed to see.
*/
@Component
public class GroupsTreeBuilder {
......
package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.model.response.PaginatedData;
import it.inaf.ia2.gms.model.response.SearchResponseItem;
import it.inaf.ia2.gms.model.response.SearchResponseType;
import it.inaf.ia2.gms.model.response.UserSearchResponse;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.rap.RapClient;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class SearchService {
@Autowired
private RapClient rapClient;
@Autowired
private GroupsService groupsService;
@Autowired
private GroupsDAO groupsDAO;
@Autowired
private PermissionsDAO permissionsDAO;
@Autowired
private MembershipsDAO membershipsDAO;
/**
* Generic search (both groups and users).
*/
public PaginatedData<SearchResponseItem> search(String query, String userId, int page, int pageSize) {
List<SearchResponseItem> items = searchUsers(query);
items.addAll(searchGroups(query, userId));
// sort by label
items.sort((i1, i2) -> i1.getLabel().compareTo(i2.getLabel()));
return new PaginatedData<>(items, page, pageSize);
}
private List<SearchResponseItem> searchUsers(String query) {
return rapClient.searchUsers(query).stream()
.map(u -> {
SearchResponseItem item = new SearchResponseItem();
item.setType(SearchResponseType.USER);
item.setId(u.getId());
item.setLabel(u.getDisplayName());
return item;
})
.collect(Collectors.toList());
}
private List<SearchResponseItem> searchGroups(String query, String userId) {
List<GroupEntity> allGroups = groupsDAO.searchGroups(query);
// Select only the groups visible to the user
List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(userId);
List<SearchResponseItem> items = new ArrayList<>();
for (GroupEntity group : allGroups) {
PermissionUtils.getGroupPermission(group, permissions).ifPresent(permission -> {
SearchResponseItem item = new SearchResponseItem();
item.setType(SearchResponseType.GROUP);
item.setId(group.getId());
item.setLabel(group.getName());
items.add(item);
});
}
return items;
}
/**
* Retrieve additional data about an user displayed into the generic search.
*
* @param actorUserId the user who performed the search
* @param targetUserId the user displayed into the search results
*/
public UserSearchResponse getUserSearchResult(String actorUserId, String targetUserId) {
List<GroupEntity> allGroups = membershipsDAO.getUserMemberships(targetUserId);
// Select only the groups visible to the user
List<PermissionEntity> permissions = permissionsDAO.findUserPermissions(actorUserId);
List<GroupEntity> visibleGroups = new ArrayList<>();
for (GroupEntity group : allGroups) {
PermissionUtils.getGroupPermission(group, permissions).ifPresent(permission -> {
visibleGroups.add(group);
});
}
UserSearchResponse response = new UserSearchResponse();
response.setGroups(visibleGroups);
// Super-admin user is able to see also other user permissions
PermissionUtils.getGroupPermission(groupsService.getRoot(), permissions).ifPresent(permission -> {
if (permission.equals(Permission.ADMIN)) {
List<PermissionEntity> targetUserPermissions = permissionsDAO.findUserPermissions(targetUserId);
response.setPermissions(targetUserPermissions);
}
});
return response;
}
}
package it.inaf.ia2.gms.controller;
import com.fasterxml.jackson.databind.ObjectMapper;
import it.inaf.ia2.gms.authn.SessionData;
import it.inaf.ia2.gms.model.response.PaginatedData;
import it.inaf.ia2.gms.model.response.SearchResponseItem;
import it.inaf.ia2.gms.model.response.UserSearchResponse;
import it.inaf.ia2.gms.service.SearchService;
import java.util.ArrayList;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.eq;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.http.MediaType;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@RunWith(MockitoJUnitRunner.class)
public class SearchControllerTest {
@Mock
private SessionData session;
@Mock
private SearchService searchService;
@InjectMocks
private SearchController controller;
private MockMvc mockMvc;
private final ObjectMapper mapper = new ObjectMapper();
@Before
public void init() {
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
when(session.getUserId()).thenReturn("admin_id");
}
@Test
public void testGenericSearch() throws Exception {
PaginatedData<SearchResponseItem> response = new PaginatedData<>(new ArrayList<>(), 1, 10);
when(searchService.search(any(), any(), anyInt(), anyInt())).thenReturn(response);
mockMvc.perform(get("/search?query=searchText&page=1&pageSize=10")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
verify(searchService, times(1)).search(eq("searchText"), eq("admin_id"), eq(1), eq(10));
}
@Test
public void testUserSearch() throws Exception {
when(searchService.getUserSearchResult(any(), any())).thenReturn(new UserSearchResponse());
mockMvc.perform(get("/search/user/user_id")
.contentType(MediaType.APPLICATION_JSON_UTF8))
.andExpect(status().isOk());
verify(searchService, times(1)).getUserSearchResult(eq("admin_id"), eq("user_id"));
}
}
package it.inaf.ia2.gms.service;
import it.inaf.ia2.gms.model.Identity;
import it.inaf.ia2.gms.model.IdentityType;
import it.inaf.ia2.gms.model.Permission;
import it.inaf.ia2.gms.model.RapUser;
import it.inaf.ia2.gms.model.response.PaginatedData;
import it.inaf.ia2.gms.model.response.SearchResponseItem;
import it.inaf.ia2.gms.model.response.SearchResponseType;
import it.inaf.ia2.gms.model.response.UserSearchResponse;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.PermissionsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import it.inaf.ia2.gms.persistence.model.PermissionEntity;
import it.inaf.ia2.gms.rap.RapClient;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import static org.mockito.Mockito.when;
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class SearchServiceTest {
@Mock
private RapClient rapClient;
@Mock
private GroupsService groupsService;
@Mock
private GroupsDAO groupsDAO;
@Mock
private PermissionsDAO permissionsDAO;
@Mock
private MembershipsDAO membershipsDAO;
@InjectMocks
private SearchService searchService;
@Test
public void testGenericSearch() {
RapUser user = new RapUser();
user.setId("user_id");
Identity identity = new Identity();
identity.setPrimary(true);
identity.setType(IdentityType.EDU_GAIN);
identity.setEmail("user@inaf.it");
user.setIdentities(Collections.singletonList(identity));
when(rapClient.searchUsers(any())).thenReturn(Collections.singletonList(user));
GroupEntity group1 = new GroupEntity();
group1.setId("group1_id");
group1.setName("Group 1");
group1.setPath("group1_id");
GroupEntity group2 = new GroupEntity();
group2.setId("group2_id");
group2.setName("Group 2");
group2.setPath("group2_id");
List<GroupEntity> allGroups = new ArrayList<>();
allGroups.add(group1);
allGroups.add(group2);
when(groupsDAO.searchGroups(any())).thenReturn(allGroups);
PermissionEntity permission = new PermissionEntity();
permission.setGroupId("group1_id");
permission.setUserId("manager_id");
permission.setGroupPath("group1_id");
permission.setPermission(Permission.MANAGE_MEMBERS);
when(permissionsDAO.findUserPermissions(any())).thenReturn(
Collections.singletonList(permission));
PaginatedData<SearchResponseItem> response = searchService.search("foo", "manager_id", 1, 10);
assertEquals(2, response.getTotalItems());
SearchResponseItem item0 = response.getItems().get(0);
assertEquals(SearchResponseType.GROUP, item0.getType());
assertEquals("group1_id", item0.getId());
assertEquals("Group 1", item0.getLabel());
SearchResponseItem item1 = response.getItems().get(1);
assertEquals(SearchResponseType.USER, item1.getType());
assertEquals("user_id", item1.getId());
assertEquals("user@inaf.it (EduGAIN)", item1.getLabel());
}
@Test
public void testGetUserSearchResult() {
GroupEntity group1 = new GroupEntity();
group1.setId("group1_id");
group1.setName("Group 1");
group1.setPath("group1_id");
when(membershipsDAO.getUserMemberships(any()))
.thenReturn(Collections.singletonList(group1));
PermissionEntity adminPermission = new PermissionEntity();
adminPermission.setGroupId("ROOT");
adminPermission.setUserId("admin_id");
adminPermission.setGroupPath("");
adminPermission.setPermission(Permission.ADMIN);
when(permissionsDAO.findUserPermissions(eq("admin_id")))
.thenReturn(Collections.singletonList(adminPermission));
GroupEntity root = new GroupEntity();
root.setId("ROOT");
root.setName("Root");
root.setPath("");
when(groupsService.getRoot()).thenReturn(root);
UserSearchResponse response = searchService.getUserSearchResult("admin_id", "target_id");
assertEquals(1, response.getGroups().size());
assertNotNull(response.getPermissions());
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment