From e28399a597c602a49892948a7467d45b0a505bcc Mon Sep 17 00:00:00 2001 From: filip franek Date: Thu, 31 Oct 2013 12:22:27 +0100 Subject: [PATCH] ROResource Access Control Filter implemented adn tested. --- .gitignore | 3 +- .../filters/ROsResourceFilter.java | 171 +++++++++++++++--- .../filters/AccessControlROsResourceTest.java | 44 +++++ 3 files changed, 196 insertions(+), 22 deletions(-) create mode 100644 src/test/java/pl/psnc/dl/wf4ever/accesscontrol/filters/AccessControlROsResourceTest.java diff --git a/.gitignore b/.gitignore index eda9b2d9..b6acff13 100644 --- a/.gitignore +++ b/.gitignore @@ -5,4 +5,5 @@ /rosrs.log /.checkstyle *~ -/tokens \ No newline at end of file +/tokens +/build diff --git a/src/main/java/pl/psnc/dl/wf4ever/accesscontrol/filters/ROsResourceFilter.java b/src/main/java/pl/psnc/dl/wf4ever/accesscontrol/filters/ROsResourceFilter.java index 8bde2aa3..a4525c05 100644 --- a/src/main/java/pl/psnc/dl/wf4ever/accesscontrol/filters/ROsResourceFilter.java +++ b/src/main/java/pl/psnc/dl/wf4ever/accesscontrol/filters/ROsResourceFilter.java @@ -1,11 +1,27 @@ package pl.psnc.dl.wf4ever.accesscontrol.filters; +import java.net.URI; +import java.util.List; + import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.WebApplicationException; import javax.ws.rs.core.Context; import javax.ws.rs.core.UriInfo; import org.apache.log4j.Logger; +import pl.psnc.dl.wf4ever.accesscontrol.dicts.Mode; +import pl.psnc.dl.wf4ever.accesscontrol.dicts.Role; +import pl.psnc.dl.wf4ever.accesscontrol.model.AccessMode; +import pl.psnc.dl.wf4ever.accesscontrol.model.Permission; +import pl.psnc.dl.wf4ever.accesscontrol.model.dao.ModeDAO; +import pl.psnc.dl.wf4ever.accesscontrol.model.dao.PermissionDAO; +import pl.psnc.dl.wf4ever.db.UserProfile; +import pl.psnc.dl.wf4ever.db.dao.UserProfileDAO; +import pl.psnc.dl.wf4ever.dl.UserMetadata; +import pl.psnc.dl.wf4ever.exceptions.ForbiddenException; +import pl.psnc.dl.wf4ever.model.Builder; + import com.sun.jersey.spi.container.ContainerRequest; import com.sun.jersey.spi.container.ContainerRequestFilter; @@ -17,31 +33,144 @@ */ public class ROsResourceFilter implements ContainerRequestFilter { - /** logger. */ - private static final Logger LOGGER = Logger.getLogger(ROsResourceFilter.class); + /** logger. */ + private static final Logger LOGGER = Logger + .getLogger(ROsResourceFilter.class); + + /** URI info. */ + @Context + private UriInfo uriInfo; + + /** HTTP request. */ + @Context + private HttpServletRequest httpRequest; + + /** Profile DAO. */ + private UserProfileDAO profileDao = new UserProfileDAO(); + + /** User Metadata. */ + private UserMetadata user; + + /** User Profile. */ + private UserProfile userProfile; + + /** Access Mode DAO. */ + private ModeDAO modeDao = new ModeDAO(); + + /** Permission DAO. */ + private PermissionDAO permissionDAO = new PermissionDAO(); + + @Override + public ContainerRequest filter(ContainerRequest request) { + Builder builder = (Builder) httpRequest.getAttribute("Builder"); + user = builder.getUser(); + if (user.equals(UserProfile.ADMIN)) { + return request; + } + userProfile = profileDao.findByLogin(user.getLogin()); + ROType resourceType = discoverResource(request.getPath()); + AccessMode mode = null; + URI roUri = null; + if (resourceType != ROType.RO_COLLECTION) { + roUri = getRootROUri(request.getPath()); + List permissions = permissionDAO + .findByResearchObject(roUri.toString()); + mode = modeDao.findByResearchObject(roUri.toString()); + if (permissions == null || permissions.size() == 0 || mode == null) { + LOGGER.warn("Permissions for ro: " + roUri.toString() + + " couldn't be calculated."); + return request; + } + } + + // handle create operation + if (request.getMethod().equals("POST") + && resourceType == ROType.RO_COLLECTION) { + // just check if user isn't anonymous to make let him create new ro + if (user.equals(userProfile.PUBLIC)) { + throw new ForbiddenException( + "User must be logged in to create a new RO"); + } else { + return request; + } + } + // if user is an author + List owners = permissionDAO.findByUserROAndPermission( + userProfile, roUri.toString(), Role.OWNER); + if (owners != null) { + if (owners.size() > 1) { + LOGGER.error("Ro " + roUri + " has more them one owner"); + throw new WebApplicationException(500); + } else if (owners.size() == 1) { + // it's an owner, full permissions + return request; + } + } - /** URI info. */ - @Context - private UriInfo uriInfo; + // if it's an access to the public resource + if (request.getMethod().equals("GET")) { + if (mode.getMode().equals(Mode.PUBLIC)) { + return request; + } + // first iterations doesn't include permission links + // just cut out all requests to private resource + if (mode.getMode().equals(Mode.PUBLIC)) { + return request; + } + } + // if there is edit request (POST,PUT,DELETE) chec if user has a writer + // permission + if (request.getMethod().equals("POST") + || request.getMethod().equals("DELETE") + || request.getMethod().equals("PUT")) { + List editors = permissionDAO.findByUserROAndPermission( + userProfile, roUri.toString(), Role.EDITOR); + if (editors != null && editors.size() > 1) { + LOGGER.warn("There in a duplicated permission for the user " + + userProfile.getLogin() + " and ro " + + roUri.toString()); + return request; + } + if (editors != null && editors.size() == 1) { + return request; + } else { + throw new ForbiddenException("User " + userProfile.getLogin() + + " deosn't have permission to modify " + + roUri.toString()); + } - /** HTTP request. */ - @Context - private HttpServletRequest httpRequest; + } + return request; + } + private ROType discoverResource(String path) { + String[] requestPathArray = path.split("ROs"); + if (requestPathArray.length == 1) { + return ROType.RO_COLLECTION; + } + String resourcePath = requestPathArray[1]; + if (resourcePath.replace("/", "").equals("") + && resourcePath.split("/").length == 2) { + return ROType.RO_COLLECTION; + } + requestPathArray = path.split("ROs/"); + resourcePath = requestPathArray[1]; + return ROType.RESOURCE; + } - @Override - public ContainerRequest filter(ContainerRequest request) { - //we can take care only + enum ROType { + RESOURCE, RO_COLLECTION + } - //there are several rules which tells which user read or edit RO - //first if user is an author they can do everything - //if RO is public ... - //... then everybody can read - //... and users with special permissions can edit - //if RO is private - //... nobody apart from author can read - //if RO is accessed via permission link then RO can be read by everybody with link and can be edited is someone has a special permission. - return request; - } + private URI getRootROUri(String path) { + String base = path.split("ROs/")[0] + "ROs/"; + String resource = path.split(uriInfo.getBaseUriBuilder().path("ROs/") + .toString())[1]; + if (resource.split("/").length == 1) { + return URI.create(base + resource); + } else { + return URI.create(base + resource.split("/")[0] + "/"); + } + } } diff --git a/src/test/java/pl/psnc/dl/wf4ever/accesscontrol/filters/AccessControlROsResourceTest.java b/src/test/java/pl/psnc/dl/wf4ever/accesscontrol/filters/AccessControlROsResourceTest.java new file mode 100644 index 00000000..a5b84109 --- /dev/null +++ b/src/test/java/pl/psnc/dl/wf4ever/accesscontrol/filters/AccessControlROsResourceTest.java @@ -0,0 +1,44 @@ +package pl.psnc.dl.wf4ever.accesscontrol.filters; + +import java.net.URI; + +import javax.ws.rs.core.MediaType; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.junit.experimental.categories.Category; + +import pl.psnc.dl.wf4ever.accesscontrol.AccessControlTest; +import pl.psnc.dl.wf4ever.accesscontrol.dicts.Role; +import pl.psnc.dl.wf4ever.accesscontrol.model.Permission; +import pl.psnc.dl.wf4ever.integration.IntegrationTest; + +import com.sun.jersey.api.client.ClientResponse; + +@Category(IntegrationTest.class) +public class AccessControlROsResourceTest extends AccessControlTest { + + @Override + @Before + public void setUp() + throws Exception { + super.setUp(); + } + + + @Override + @After + public void tearDown() + throws Exception { + super.tearDown(); + } + + + @Test + public void testIfOnlyOnwerCanReadAndWriteModes() { + URI createdRO = createRO(accessToken); + } + +}