Commit 3d0b64ff authored by Piotr Gawron's avatar Piotr Gawron
Browse files

serialization for Privilege implemented

parent 3a041ece
......@@ -3,14 +3,28 @@ package lcsb.mapviewer.model.security;
import java.io.Serializable;
import java.util.Objects;
import javax.persistence.*;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import lcsb.mapviewer.modelutils.serializer.model.security.PrivilegeDeserializer;
import lcsb.mapviewer.modelutils.serializer.model.security.PrivilegeSerializer;
@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "type", "objectId" }))
@JsonSerialize(using = PrivilegeSerializer.class)
@JsonDeserialize(using = PrivilegeDeserializer.class)
public class Privilege implements Serializable {
private static final long serialVersionUID = 1L;
......
package lcsb.mapviewer.modelutils.serializer.model.security;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import com.fasterxml.jackson.databind.node.ObjectNode;
import lcsb.mapviewer.model.security.Privilege;
public class PrivilegeDeserializer extends StdDeserializer<Privilege> {
/**
*
*/
private static final long serialVersionUID = 1L;
public PrivilegeDeserializer() {
super(Privilege.class);
}
@Override
public Privilege deserialize(JsonParser parser, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = (ObjectMapper) parser.getCodec();
ObjectNode rootNode = mapper.readTree(parser);
return new PrivilegeKeyDeserializer().deserializeKey(rootNode.asText(), ctxt);
}
}
package lcsb.mapviewer.modelutils.serializer.model.security;
import java.io.IOException;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.KeyDeserializer;
import lcsb.mapviewer.common.exception.DeserializationException;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.security.PrivilegeType;
public class PrivilegeKeyDeserializer extends KeyDeserializer {
@Override
public Privilege deserializeKey(String key, DeserializationContext ctxt) throws IOException {
String[] tokens = key.split(":");
if (tokens.length > 2) {
throw new DeserializationException("Invalid privilege: " + key);
}
if (tokens.length == 1) {
return new Privilege(PrivilegeType.valueOf(tokens[0]));
}
return new Privilege(PrivilegeType.valueOf(tokens[0]), tokens[1]);
}
}
\ No newline at end of file
package lcsb.mapviewer.modelutils.serializer.model.security;
import java.io.IOException;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import lcsb.mapviewer.model.security.Privilege;
public class PrivilegeSerializer extends JsonSerializer<Privilege> {
@Override
public void serialize(final Privilege entry, final JsonGenerator gen,
final SerializerProvider serializers)
throws IOException {
if (entry.isObjectPrivilege()) {
gen.writeString(entry.getType()+":"+entry.getObjectId());
} else {
gen.writeString(entry.getType().name());
}
}
}
\ No newline at end of file
......@@ -28,12 +28,16 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lcsb.mapviewer.api.BaseController;
import lcsb.mapviewer.api.OperationNotAllowedException;
import lcsb.mapviewer.common.Configuration;
import lcsb.mapviewer.common.exception.InvalidStateException;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.user.ConfigurationElementType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.modelutils.serializer.model.security.PrivilegeKeyDeserializer;
import lcsb.mapviewer.services.InvalidTokenException;
import lcsb.mapviewer.services.ObjectNotFoundException;
import lcsb.mapviewer.services.QueryException;
......@@ -84,14 +88,17 @@ public class UserController extends BaseController {
return userRest.getUser(login, columns);
}
public static class UserPrivilegesDTO {
@JsonDeserialize(keyUsing = PrivilegeKeyDeserializer.class)
public Map<Privilege, Boolean> privileges = new HashMap<>();
}
@PreAuthorize("hasAuthority('IS_ADMIN')")
@PatchMapping(value = "/users/{login}:updatePrivileges")
@PatchMapping(value = "/users/{login}:updatePrivileges", consumes = { MediaType.APPLICATION_JSON_VALUE})
public UserDTO updatePrivileges(
@RequestBody String body,
@RequestBody UserPrivilegesDTO data,
@PathVariable(value = "login") String login) throws IOException, QueryException {
Map<String, Object> node = parseBody(body);
Map<String, Object> data = getData(node, "privileges");
return userRest.updatePrivileges(login, data);
return userRest.updatePrivileges(login, data.privileges);
}
@PreAuthorize("hasAuthority('IS_ADMIN') or #login == authentication.name")
......
......@@ -23,6 +23,7 @@ import org.springframework.util.MultiValueMap;
import lcsb.mapviewer.api.BaseRestImpl;
import lcsb.mapviewer.api.UpdateConflictException;
import lcsb.mapviewer.model.security.Privilege;
import lcsb.mapviewer.model.security.PrivilegeType;
import lcsb.mapviewer.model.user.User;
import lcsb.mapviewer.model.user.UserAnnotationSchema;
......@@ -163,8 +164,8 @@ public class UserRestImpl extends BaseRestImpl {
return result;
}
public UserDTO updatePrivileges(String login, Map<String, Object> privilegesData) throws QueryException {
if (privilegesData == null) {
public UserDTO updatePrivileges(String login, Map<Privilege, Boolean> data) throws QueryException {
if (data == null) {
throw new QueryException("Privileges not defined");
}
......@@ -173,39 +174,25 @@ public class UserRestImpl extends BaseRestImpl {
throw new QueryException("User does not exist.");
}
for (String privilege : privilegesData.keySet()) {
String[] split = privilege.split(":");
if (split.length > 2) {
throw new QueryException("Invalid privilege format.");
}
PrivilegeType type;
try {
type = PrivilegeType.valueOf(split[0]);
} catch (IllegalArgumentException e) {
throw new QueryException("Privilege does not exist.", e);
}
for (Privilege privilege : data.keySet()) {
boolean grant;
try {
grant = (boolean) privilegesData.get(privilege);
grant = (boolean) data.get(privilege);
} catch (ClassCastException e) {
throw new QueryException("Privilege can only be set to true (grant) or false (revoke).", e);
}
boolean isObjectPrivilege = split.length > 1;
if (isObjectPrivilege) {
if (privilege.isObjectPrivilege()) {
if (grant) {
getUserService().grantUserPrivilege(user, type, split[1]);
getUserService().grantUserPrivilege(user, privilege.getType(), privilege.getObjectId());
} else {
getUserService().revokeUserPrivilege(user, type, split[1]);
getUserService().revokeUserPrivilege(user, privilege.getType(), privilege.getObjectId());
}
} else {
if (grant) {
getUserService().grantUserPrivilege(user, type);
getUserService().grantUserPrivilege(user, privilege.getType());
} else {
getUserService().revokeUserPrivilege(user, type);
getUserService().revokeUserPrivilege(user, privilege.getType());
}
}
}
......
......@@ -54,6 +54,7 @@ import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
import lcsb.mapviewer.annotation.services.annotators.UniprotAnnotator;
import lcsb.mapviewer.api.users.UserController.UserPrivilegesDTO;
import lcsb.mapviewer.api.users.UserPreferencesDTO;
import lcsb.mapviewer.api.users.UserRestImpl;
import lcsb.mapviewer.model.Project;
......@@ -138,10 +139,12 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
public void grantPrivilege() throws Exception {
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
String body = "{\"privileges\":{\"IS_ADMIN\":true}}";
UserPrivilegesDTO data = new UserPrivilegesDTO();
data.privileges.put(new Privilege(PrivilegeType.IS_ADMIN), true);
RequestBuilder request = patch("/api/users/{login}:updatePrivileges", TEST_USER_LOGIN)
.content(body)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(data))
.session(session);
mockMvc.perform(request)
......@@ -160,10 +163,12 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
public void grantPrivilegeForNonExistingUser() throws Exception {
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
String body = "{\"privileges\":{\"IS_ADMIN\":true}}";
UserPrivilegesDTO data = new UserPrivilegesDTO();
data.privileges.put(new Privilege(PrivilegeType.IS_ADMIN), true);
RequestBuilder request = patch("/api/users/unkown_login:updatePrivileges")
.content(body)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(data))
.session(session);
mockMvc.perform(request)
......@@ -181,10 +186,12 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
return null;
});
String body = "{\"privileges\":{\"IS_ADMIN\":false}}";
UserPrivilegesDTO data = new UserPrivilegesDTO();
data.privileges.put(new Privilege(PrivilegeType.IS_ADMIN), false);
RequestBuilder request = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.content(body)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(data))
.session(session);
mockMvc.perform(request)
......@@ -206,10 +213,12 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
String body = "{\"privileges\":{\"READ_PROJECT:" + project.getProjectId() + "\":true}}";
UserPrivilegesDTO data = new UserPrivilegesDTO();
data.privileges.put(new Privilege(PrivilegeType.READ_PROJECT, project.getProjectId()), true);
RequestBuilder request = patch("/api/users/{login}:updatePrivileges", TEST_USER_LOGIN)
.content(body)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(data))
.session(session);
mockMvc.perform(request)
......@@ -219,11 +228,8 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
responseFields(getUserResponseFields())))
.andExpect(status().is2xxSuccessful());
callInSeparateThread(() -> {
User user = userService.getUserByLogin(TEST_USER_LOGIN);
assertEquals(1, user.getPrivileges().size());
return null;
});
User user = userService.getUserByLogin(TEST_USER_LOGIN, true);
assertEquals(1, user.getPrivileges().size());
}
......@@ -245,6 +251,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
String body = "{\"privileges\":{\"XYZ\":true}}";
RequestBuilder request = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.session(session);
......@@ -256,10 +263,12 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
public void grantInvalidProjectPrivilege() throws Exception {
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
String body = "{\"privileges\":{\"READ_PROJECT:-5:-1\":true}}";
UserPrivilegesDTO data = new UserPrivilegesDTO();
data.privileges.put(new Privilege(PrivilegeType.READ_PROJECT, "-5:-1"), true);
RequestBuilder request = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.content(body)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsString(data))
.session(session);
mockMvc.perform(request)
......@@ -273,6 +282,7 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
String body = "{\"privileges\":{\"IS_ADMIN\":\"surprise\"}}";
RequestBuilder request = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.contentType(MediaType.APPLICATION_JSON)
.content(body)
.session(session);
......@@ -291,14 +301,20 @@ public class UserControllerIntegrationTest extends ControllerIntegrationTest {
MockHttpSession session = createSession(BUILT_IN_TEST_ADMIN_LOGIN, BUILT_IN_TEST_ADMIN_PASSWORD);
String grantBody = "{\"privileges\":{\"READ_PROJECT:" + project.getId() + "\":true}}";
String revokeBody = "{\"privileges\":{\"READ_PROJECT:" + project.getId() + "\":false}}";
UserPrivilegesDTO grantData = new UserPrivilegesDTO();
grantData.privileges.put(new Privilege(PrivilegeType.READ_PROJECT, project.getProjectId()), true);
UserPrivilegesDTO revokeData = new UserPrivilegesDTO();
revokeData.privileges.put(new Privilege(PrivilegeType.READ_PROJECT, project.getProjectId()), false);
RequestBuilder grantRequest = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.content(grantBody)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(grantData))
.session(session);
RequestBuilder revokeRequest = patch("/api/users/" + TEST_USER_LOGIN + ":updatePrivileges")
.content(revokeBody)
.contentType(MediaType.APPLICATION_JSON)
.content(objectMapper.writeValueAsBytes(revokeData))
.session(session);
mockMvc.perform(grantRequest)
......
Markdown is supported
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