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

Added /search/{groups} isMemberOf IVOA GMS endpoint

parent bc79d18c
......@@ -14,12 +14,14 @@ import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.servlet.http.HttpServletResponse;
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.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
......@@ -64,6 +66,62 @@ public class JWTWebServiceController {
}
}
/**
* This endpoint is compliant with the IVOA GMS standard. Warning: for
* supporting the groups of groups (with dots inside) the path variable must
* be defined adding ".+", otherwise Spring will think it is a file
* extension (thanks https://stackoverflow.com/a/16333149/771431)
*/
@GetMapping(value = "/search/{group:.+}", produces = MediaType.TEXT_PLAIN_VALUE)
public void isMemberOf(@PathVariable("group") String group, Principal principal, HttpServletResponse response) throws IOException {
String userId = principal.getName();
List<String> groupNames = extractGroupNames(group);
boolean isMemeber = false;
String parentPath = ""; // starting from ROOT
for (String groupName : groupNames) {
Optional<GroupEntity> optionalGroup = groupsDAO.findGroupByParentAndName(parentPath, groupName);
if (optionalGroup.isPresent()) {
GroupEntity groupEntity = optionalGroup.get();
parentPath = groupEntity.getPath();
isMemeber = membershipsDAO.isMemberOf(userId, groupEntity.getId());
if (isMemeber) {
break;
}
} else {
break;
}
}
if (isMemeber) {
try (PrintWriter pw = new PrintWriter(response.getOutputStream())) {
pw.println(group);
}
}
// else: empty response (as defined by GMS standard)
}
private List<String> extractGroupNames(String groupStr) {
List<String> names = new ArrayList<>();
String currentName = "";
for (int i = 0; i < groupStr.length(); i++) {
char c = groupStr.charAt(i);
// dot is the group separator and it must be escaped if used inside
// group names
if (c == '.' && groupStr.charAt(i - 1) != '\\') {
names.add(currentName.replace("\\.", "."));
currentName = "";
} else {
currentName += c;
}
}
names.add(currentName);
return names;
}
private Set<String> getAllIdentifiers(List<GroupEntity> groups) {
Set<String> allIdentifiers = new HashSet<>();
......
......@@ -53,16 +53,20 @@ public class LoggingDAO {
}
public void logAction(String action) {
String sql = "INSERT INTO audit_log (\"user\", action, ip_address) VALUES (?, ?, ?)";
try {
String sql = "INSERT INTO audit_log (\"user\", action, ip_address) VALUES (?, ?, ?)";
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
int i = 0;
ps.setString(++i, getUser());
ps.setString(++i, action);
ps.setString(++i, getIPAddress());
return ps;
});
jdbcTemplate.update(conn -> {
PreparedStatement ps = conn.prepareStatement(sql);
int i = 0;
ps.setString(++i, getUser());
ps.setString(++i, action);
ps.setString(++i, getIPAddress());
return ps;
});
} catch (Throwable t) {
LOG.error("Exception while trying to save audit log", t);
}
}
private String getIPAddress() {
......
package it.inaf.ia2.gms.controller;
import it.inaf.ia2.gms.persistence.GroupsDAO;
import it.inaf.ia2.gms.persistence.MembershipsDAO;
import it.inaf.ia2.gms.persistence.model.GroupEntity;
import java.security.Principal;
import java.util.Optional;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.mockito.ArgumentMatchers.anyString;
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;
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.content;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
@RunWith(MockitoJUnitRunner.class)
public class JWTWebServiceControllerTest {
@Mock
private MembershipsDAO membershipsDAO;
@Mock
private GroupsDAO groupsDAO;
@InjectMocks
private JWTWebServiceController controller;
private final Principal principal = new Principal() {
@Override
public String getName() {
return "TEST_PRINCIPAL";
}
};
private MockMvc mockMvc;
@Before
public void init() {
mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
}
@Test
public void testIsMemberOf() throws Exception {
GroupEntity group1 = new GroupEntity();
group1.setId("1");
group1.setPath("1");
group1.setName("group.1");
GroupEntity group2 = new GroupEntity();
group2.setId("2");
group2.setPath("1.2");
group2.setName("subgroup");
GroupEntity group3 = new GroupEntity();
group3.setId("3");
group3.setPath("1.2.3");
group3.setName("subsubgroup");
when(groupsDAO.findGroupByParentAndName(eq(""), eq("group.1")))
.thenReturn(Optional.of(group1));
when(groupsDAO.findGroupByParentAndName(eq("1"), eq("subgroup")))
.thenReturn(Optional.of(group2));
when(groupsDAO.findGroupByParentAndName(eq("1.2"), eq("subsubgroup")))
.thenReturn(Optional.of(group3));
when(membershipsDAO.isMemberOf(anyString(), eq(group3.getId()))).thenReturn(true);
String group = "group\\.1.subgroup.subsubgroup";
mockMvc.perform(get("/ws/jwt/search/" + group).principal(principal))
.andExpect(status().isOk())
.andExpect(content().string(group + "\n"));
}
}
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