Skip to content

Commit

Permalink
Implement *real* webac delegate + unit tests
Browse files Browse the repository at this point in the history
  • Loading branch information
acoburn authored and Andrew Woods committed Sep 7, 2015
1 parent 297cad3 commit 7e5b14d
Show file tree
Hide file tree
Showing 2 changed files with 206 additions and 13 deletions.
Expand Up @@ -15,9 +15,24 @@
*/
package org.fcrepo.auth.webac;

import static java.util.Collections.unmodifiableMap;
import static org.fcrepo.auth.webac.URIConstants.FOAF_AGENT_VALUE;
import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_CONTROL_VALUE;
import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_READ_VALUE;
import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_WRITE_VALUE;
import static org.modeshape.jcr.ModeShapePermissions.ADD_NODE;
import static org.modeshape.jcr.ModeShapePermissions.MODIFY_ACCESS_CONTROL;
import static org.modeshape.jcr.ModeShapePermissions.READ;
import static org.modeshape.jcr.ModeShapePermissions.READ_ACCESS_CONTROL;
import static org.modeshape.jcr.ModeShapePermissions.REGISTER_NAMESPACE;
import static org.modeshape.jcr.ModeShapePermissions.REMOVE;
import static org.modeshape.jcr.ModeShapePermissions.REMOVE_CHILD_NODES;
import static org.modeshape.jcr.ModeShapePermissions.SET_PROPERTY;

import java.security.Principal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.jcr.Session;
Expand All @@ -41,6 +56,24 @@ public class WebACAuthorizationDelegate extends AbstractRolesAuthorizationDelega
*/
private static final Logger LOGGER = LoggerFactory.getLogger(WebACAuthorizationDelegate.class);

private static final Map<String, String> actionMap;

static {
final Map<String, String> map = new HashMap<>();
// WEBAC_MODE_READ Permissions
map.put(READ, WEBAC_MODE_READ_VALUE);
// WEBAC_MODE_WRITE Permissions
map.put(ADD_NODE, WEBAC_MODE_WRITE_VALUE);
map.put(REGISTER_NAMESPACE, WEBAC_MODE_WRITE_VALUE);
map.put(REMOVE, WEBAC_MODE_WRITE_VALUE);
map.put(REMOVE_CHILD_NODES, WEBAC_MODE_WRITE_VALUE);
map.put(SET_PROPERTY, WEBAC_MODE_WRITE_VALUE);
// WEBAC_MODE_CONTROL Permissions
map.put(MODIFY_ACCESS_CONTROL, WEBAC_MODE_CONTROL_VALUE);
map.put(READ_ACCESS_CONTROL, WEBAC_MODE_CONTROL_VALUE);
actionMap = unmodifiableMap(map);
}

/**
* The security principal for every request, that represents the foaf:Agent agent class that is used to designate
* "everyone".
Expand All @@ -62,7 +95,27 @@ public String toString() {
@Override
public boolean rolesHavePermission(final Session userSession, final String absPath,
final String[] actions, final Set<String> roles) {
final boolean permit = false;

/*
* If any value in the actions Array is NOT also in the roles Set, the request should be denied.
* Otherwise, e.g. all of the actions values are contained in the roles set, the request is approved.
*
* The logic here may not be immediately obvious. The process is thus:
* map: map the modeshape action to a webac action
* filter: ALL of these actions MUST exist in the roles Set, so if any action
* value does NOT exist in the roles Set, we want to know about that
* findFirst: If any value makes it through that filter, it is enough to invalidate
* the request. This is evaluated lazily, so the first item encountered will
* short-circut the processing of the rest of the stream.
* isPresent: this returns true if any value passed through the filter, but we
* actually want to invert that logic, hence the ! at the beginning of the expression.
*/
final boolean permit = !Arrays.asList(actions).stream()
.map(actionMap::get)
.filter(x -> !roles.contains(x))
.findFirst()
.isPresent();

LOGGER.debug("Request for actions: {}, on path: {}, with roles: {}. Permission={}",
actions,
absPath,
Expand Down
164 changes: 152 additions & 12 deletions src/test/java/org/fcrepo/auth/webac/WebACAuthorizationDelegateTest.java
Expand Up @@ -15,14 +15,29 @@
*/
package org.fcrepo.auth.webac;

import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_CONTROL_VALUE;
import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_READ_VALUE;
import static org.fcrepo.auth.webac.URIConstants.WEBAC_MODE_WRITE_VALUE;
import static org.modeshape.jcr.ModeShapePermissions.ADD_NODE;
import static org.modeshape.jcr.ModeShapePermissions.MODIFY_ACCESS_CONTROL;
import static org.modeshape.jcr.ModeShapePermissions.READ;
import static org.modeshape.jcr.ModeShapePermissions.READ_ACCESS_CONTROL;
import static org.modeshape.jcr.ModeShapePermissions.REGISTER_NAMESPACE;
import static org.modeshape.jcr.ModeShapePermissions.REMOVE;
import static org.modeshape.jcr.ModeShapePermissions.REMOVE_CHILD_NODES;
import static org.modeshape.jcr.ModeShapePermissions.SET_PROPERTY;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.util.HashSet;
import java.util.Set;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import org.modeshape.jcr.api.Session;

/**
Expand All @@ -31,6 +46,7 @@
* @author Peter Eichman
* @since Aug 24, 2015
*/
@RunWith(MockitoJUnitRunner.class)
public class WebACAuthorizationDelegateTest {

private WebACAuthorizationDelegate webacAD;
Expand All @@ -44,21 +60,145 @@ public void setUp() {
}

@Test
public void test() {
assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", getFakeActions(), getFakeRoles()));
public void testCanRead1() {
final String[] actions = {READ};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_READ_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanRead2() {
final String[] actions = {READ};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_READ_VALUE);
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotRead1() {
final String[] actions = {READ, SET_PROPERTY};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotRead2() {
final String[] actions = {READ};
final Set<String> roles = new HashSet<>();

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWrite1() {
final String[] actions = {ADD_NODE};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWrite2() {
final String[] actions = {REGISTER_NAMESPACE};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWrite3() {
final String[] actions = {REMOVE};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWrite4() {
final String[] actions = {REMOVE_CHILD_NODES};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWrite5() {
final String[] actions = {SET_PROPERTY};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

private static String[] getFakeActions() {
final String[] fakeActions = new String[2];
fakeActions[0] = "fakeAction1";
fakeActions[1] = "fakeAction2";
return fakeActions;
@Test
public void testCanWrite6() {
final String[] actions = {SET_PROPERTY, ADD_NODE, REGISTER_NAMESPACE, REMOVE, REMOVE_CHILD_NODES};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotWrite1() {
final String[] actions = {READ, SET_PROPERTY, ADD_NODE, REGISTER_NAMESPACE, REMOVE, REMOVE_CHILD_NODES};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotWrite2() {
final String[] actions = {SET_PROPERTY};
final Set<String> roles = new HashSet<>();

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

private static Set<String> getFakeRoles() {
final Set<String> fakeRoles = new HashSet<>();
fakeRoles.add("fakeRole1");
fakeRoles.add("fakeRole2");
return fakeRoles;
@Test
public void testCanReadAcl1() {
final String[] actions = {READ_ACCESS_CONTROL};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_CONTROL_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotReadAcl1() {
final String[] actions = {READ_ACCESS_CONTROL};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_READ_VALUE);

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCanWriteAcl1() {
final String[] actions = {MODIFY_ACCESS_CONTROL};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_CONTROL_VALUE);

assertTrue(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}

@Test
public void testCannotWriteAcl1() {
final String[] actions = {MODIFY_ACCESS_CONTROL};
final Set<String> roles = new HashSet<>();
roles.add(WEBAC_MODE_WRITE_VALUE);

assertFalse(webacAD.rolesHavePermission(mockSession, "/fake/path", actions, roles));
}
}

0 comments on commit 7e5b14d

Please sign in to comment.