Commit b9d62a20 authored by Sonia Zorba's avatar Sonia Zorba
Browse files

Added logic for generic search functionality

parent 18d45bca
......@@ -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());
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment