blob: 327f7c819e13354e4c39e816b6480a485955bfbe [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.jackrabbit.oak.jcr.security.user;
import java.security.Principal;
import javax.jcr.RepositoryException;
import javax.jcr.nodetype.ConstraintViolationException;
import org.apache.jackrabbit.api.JackrabbitSession;
import org.apache.jackrabbit.api.security.principal.PrincipalIterator;
import org.apache.jackrabbit.api.security.principal.PrincipalManager;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.oak.api.CommitFailedException;
import org.apache.jackrabbit.test.NotExecutableException;
import org.junit.Test;
/**
* Tests for the {@link Group} implementation specific for nested group membership.
*/
public class NestedGroupTest extends AbstractUserTest {
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
private Group createGroup(Principal p) throws RepositoryException {
Group gr = userMgr.createGroup(p);
superuser.save();
return gr;
}
private void removeGroup(Group gr) throws RepositoryException {
gr.remove();
superuser.save();
}
private boolean addMember(Group gr, Authorizable member) throws RepositoryException {
boolean added = gr.addMember(member);
superuser.save();
return added;
}
private boolean removeMember(Group gr, Authorizable member) throws RepositoryException {
boolean removed = gr.removeMember(member);
superuser.save();
return removed;
}
@Test
public void testAddGroupAsMember() throws NotExecutableException, RepositoryException {
Group gr1 = null;
Group gr2 = null;
try {
gr1 = createGroup(getTestPrincipal());
gr2 = createGroup(getTestPrincipal());
assertFalse(gr1.isMember(gr2));
assertTrue(addMember(gr1, gr2));
assertTrue(gr1.isMember(gr2));
} finally {
if (gr1 != null) {
removeMember(gr1, gr2);
removeGroup(gr1);
}
if (gr2 != null) {
removeGroup(gr2);
}
}
}
@Test
public void testAddCircularMembers() throws NotExecutableException, RepositoryException {
Group gr1 = null;
Group gr2 = null;
try {
gr1 = createGroup(getTestPrincipal());
gr2 = createGroup(getTestPrincipal());
assertTrue(addMember(gr1, gr2));
try {
assertFalse(addMember(gr2, gr1));
} catch (ConstraintViolationException e) {
// cycle detected upon save => success
assertCyclicMembershipError(e);
}
} finally {
if (gr1 != null && gr1.isMember(gr2)) {
removeMember(gr1, gr2);
}
if (gr2 != null && gr2.isMember(gr1)) {
removeMember(gr2, gr1);
}
if (gr1 != null) removeGroup(gr1);
if (gr2 != null) removeGroup(gr2);
}
}
@Test
public void testCyclicMembers2() throws RepositoryException, NotExecutableException {
Group gr1 = null;
Group gr2 = null;
Group gr3 = null;
try {
gr1 = createGroup(getTestPrincipal());
gr2 = createGroup(getTestPrincipal());
gr3 = createGroup(getTestPrincipal());
assertTrue(addMember(gr1, gr2));
assertTrue(addMember(gr2, gr3));
try {
assertFalse(addMember(gr3, gr1));
} catch (ConstraintViolationException e) {
// cycle detected upon save => success
assertCyclicMembershipError(e);
}
} finally {
if (gr1 != null) {
removeMember(gr1, gr2);
}
if (gr2 != null) {
removeMember(gr2, gr3);
removeGroup(gr2);
}
if (gr3 != null) {
removeMember(gr3, gr1);
removeGroup(gr3);
}
if (gr1 != null) removeGroup(gr1);
}
}
private static void assertCyclicMembershipError(Exception e) {
Throwable th = e.getCause();
if (th != null) {
assertTrue(th instanceof CommitFailedException);
CommitFailedException ce = (CommitFailedException) th;
assertEquals(CommitFailedException.CONSTRAINT, ce.getType());
assertEquals(31, ce.getCode());
}
}
@Test
public void testInheritedMembership() throws NotExecutableException, RepositoryException {
Group gr1 = null;
Group gr2 = null;
Group gr3 = null;
if (!(superuser instanceof JackrabbitSession)) {
throw new NotExecutableException();
}
try {
gr1 = createGroup(getTestPrincipal());
gr2 = createGroup(getTestPrincipal());
gr3 = createGroup(getTestPrincipal());
assertTrue(addMember(gr1, gr2));
assertTrue(addMember(gr2, gr3));
// NOTE: don't test with Group.isMember for not required to detect
// inherited membership -> rather with PrincipalManager.
boolean isMember = false;
PrincipalManager pmgr = ((JackrabbitSession) superuser).getPrincipalManager();
for (PrincipalIterator it = pmgr.getGroupMembership(gr3.getPrincipal());
it.hasNext() && !isMember;) {
isMember = it.nextPrincipal().equals(gr1.getPrincipal());
}
assertTrue(isMember);
} finally {
if (gr1 != null && gr1.isMember(gr2)) {
removeMember(gr1, gr2);
}
if (gr2 != null && gr2.isMember(gr3)) {
removeMember(gr2, gr3);
}
if (gr1 != null) removeGroup(gr1);
if (gr2 != null) removeGroup(gr2);
if (gr3 != null) removeGroup(gr3);
}
}
}