Skip to content

Commit

Permalink
Merge branch 'release/2.0.9'
Browse files Browse the repository at this point in the history
  • Loading branch information
ghenzler committed May 17, 2018
2 parents 515e896 + b82c03c commit d217131
Show file tree
Hide file tree
Showing 12 changed files with 221 additions and 28 deletions.
2 changes: 1 addition & 1 deletion accesscontroltool-bundle/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
<parent>
<groupId>biz.netcentric.cq.tools.accesscontroltool</groupId>
<artifactId>accesscontroltool</artifactId>
<version>2.0.8</version>
<version>2.0.9</version>
</parent>

<!-- ====================================================================== -->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import javax.jcr.ValueFactory;

import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang.ArrayUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
Expand Down Expand Up @@ -105,6 +106,19 @@ private void installAuthorizableConfigurationBean(final Session session,

// if current authorizable from config doesn't exist yet
Authorizable authorizableToInstall = userManager.getAuthorizable(authorizableId);

if(StringUtils.equals(authorizableId, PRINCIPAL_EVERYONE)) {
if (ArrayUtils.isNotEmpty(authorizableConfigBean.getMemberOf())
|| ArrayUtils.isNotEmpty(authorizableConfigBean.getMembers())
|| StringUtils.isNotBlank(authorizableConfigBean.getMigrateFrom())) {
throw new IllegalArgumentException("The special group " + PRINCIPAL_EVERYONE
+ " does not support setting properties 'members', 'isMemberOf' and 'migrateFrom'");
}
// only setting authorizables properties is supported for everyone
setAuthorizableProperties(authorizableToInstall, authorizableConfigBean, session, installLog);
return;
}

if (authorizableToInstall == null) {
authorizableToInstall = createNewAuthorizable(acConfiguration, authorizableConfigBean, installLog, userManager, session);
}
Expand All @@ -122,11 +136,13 @@ private void installAuthorizableConfigurationBean(final Session session,
// move authorizable if path changed (retaining existing members)
handleRecreationOfAuthorizableIfNecessary(session, acConfiguration, authorizableConfigBean, installLog, userManager);

applyGroupMembershipConfigIsMemberOf(installLog, acConfiguration, authorizableConfigBean, userManager, session, authorizablesFromConfigurations);
applyGroupMembershipConfigIsMemberOf(installLog, acConfiguration, authorizableConfigBean, userManager, session,
authorizablesFromConfigurations);

}

applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, installLog, authorizableId, userManager, authorizablesFromConfigurations);
applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, installLog, authorizableId, userManager,
authorizablesFromConfigurations);

if (StringUtils.isNotBlank(authorizableConfigBean.getMigrateFrom()) && authorizableConfigBean.isGroup()) {
migrateFromOldGroup(authorizableConfigBean, userManager, installLog);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ public Set<String> removeUnmanagedPrincipalNamesAtPath(String path, Set<String>
Set<String> filteredPrincipals = new HashSet<String>();
for (String principal : principals) {
AuthorizableConfigBean authorizableConfig = getAuthorizableConfigByPrincipalName(principal);
if (authorizableConfig.managesPath(path, defaultUnmanagedAcePathsRegex)) {
if (authorizableConfig == null /* happens if migrateFrom is used, #290 */
|| authorizableConfig.managesPath(path, defaultUnmanagedAcePathsRegex)) {
filteredPrincipals.add(principal);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,8 @@ public String getContentAsString() throws Exception {
StringWriter writer = new StringWriter();
IOUtils.copy(configInputStream, writer, "UTF-8");
String configData = writer.toString();
if (StringUtils.isNotBlank(configData)) {
LOG.debug("found configuration data of node: {}", node.getPath());
return configData;
} else {
throw new IllegalStateException("File " + node.getPath() + " is empty!");
}
LOG.debug("Found configuration data of node: {} with {} bytes", node.getPath(), configData.getBytes());
return configData;

} finally {
configInputStream.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@
import biz.netcentric.cq.tools.actool.configmodel.AuthorizablesConfig;
import biz.netcentric.cq.tools.actool.configmodel.GlobalConfiguration;
import biz.netcentric.cq.tools.actool.helper.Constants;
import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger;
import biz.netcentric.cq.tools.actool.history.InstallationLogger;
import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger;
import biz.netcentric.cq.tools.actool.validators.AceBeanValidator;
import biz.netcentric.cq.tools.actool.validators.AuthorizableValidator;
import biz.netcentric.cq.tools.actool.validators.ConfigurationsValidator;
Expand Down Expand Up @@ -86,10 +86,15 @@ public AcConfiguration getMergedConfigurations(
for (final Map.Entry<String, String> entry : configFileContentByFilename.entrySet()) {

String sourceFile = entry.getKey();
history.addMessage(LOG, "Found configuration file " + sourceFile);
history.addMessage(LOG, "Using configuration file " + sourceFile);

List<LinkedHashMap> yamlRootList = (List<LinkedHashMap>) yamlParser.load(entry.getValue());

if (yamlRootList == null || yamlRootList.isEmpty()) {
history.addMessage(LOG, " " + sourceFile + " has no instructions");
continue;
}

yamlRootList = yamlMacroProcessor.processMacros(yamlRootList, history, session);
// set merged config per file to ensure it is there in case of validation errors (for success, the actual merged config is set
// after this loop)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Dictionary;
Expand All @@ -18,6 +19,7 @@
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

Expand All @@ -35,6 +37,7 @@
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.UserManager;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.jcr.api.SlingRepository;
Expand Down Expand Up @@ -657,24 +660,35 @@ private String purgeAuthorizables(Set<String> authorizableIds, final Session ses

try {
// first the ACE entries have to be deleted

Set<String> principalIds = new HashSet<String>();
Set<AclBean> aclBeans = QueryHelper.getAuthorizablesAcls(session, authorizableIds, principalIds);
String deleteAcesResultMsg = PurgeHelper.deleteAcesForPrincipalIds(session, principalIds, aclBeans);
message.append(deleteAcesResultMsg);

// then the authorizables can be deleted
UserManager userManager = AccessControlUtils.getUserManagerAutoSaveDisabled(session);
List<Authorizable> authorizablesToDelete = new ArrayList<Authorizable>();
for (String authorizableId : authorizableIds) {
String deleteResultMsg = deleteAuthorizable(authorizableId, userManager);
Authorizable authorizable = userManager.getAuthorizable(authorizableId);
if (authorizable != null) {
authorizablesToDelete.add(authorizable);
} else {
message.append("Could not delete authorizable '" + authorizableId + "' because it does not exist\n");
}
}

sortAuthorizablesForDeletion(authorizablesToDelete);

for (Authorizable authorizableToDelete : authorizablesToDelete) {
String deleteResultMsg = deleteAuthorizable(authorizableToDelete);
message.append(deleteResultMsg);
}

session.save();

sw.stop();
String executionTime = PersistableInstallationLogger.msHumanReadable(sw.getTime());
message.append("Purged " + authorizableIds.size() + " authorizables in " + executionTime + "\n");
message.append("Purged " + authorizablesToDelete.size() + " authorizables in " + executionTime + "\n");

} catch (Exception e) {
message.append("Deletion of ACEs failed! reason: RepositoryException: " + e + "\n");
Expand All @@ -684,19 +698,51 @@ private String purgeAuthorizables(Set<String> authorizableIds, final Session ses
return message.toString();
}

private String deleteAuthorizable(final String authorizableId, final UserManager userManager) {
void sortAuthorizablesForDeletion(List<Authorizable> authorizablesToDelete) throws RepositoryException {

outer:
for (int i = 0; i < authorizablesToDelete.size();) {
Authorizable currentAuthorizable = authorizablesToDelete.get(i);
Iterator<Group> declaredMemberOfIt = currentAuthorizable.declaredMemberOf();
LOG.trace("At index {}: {}", i, currentAuthorizable.getID());
while (declaredMemberOfIt != null && declaredMemberOfIt.hasNext()) {
Group groupOfAuthorizable = declaredMemberOfIt.next();
int groupOfAuthorizableIndex = authorizablesToDelete.indexOf(groupOfAuthorizable);
LOG.trace(" Is member of at index {}: {}", groupOfAuthorizableIndex, groupOfAuthorizable.getID());
if (groupOfAuthorizableIndex > -1 && groupOfAuthorizableIndex < i) {
LOG.trace(" Swap at index {} (groupOfAuthorizableIndex {}):", i, groupOfAuthorizableIndex);
// swap and set i
authorizablesToDelete.set(groupOfAuthorizableIndex, currentAuthorizable);
authorizablesToDelete.set(i, groupOfAuthorizable);
i = groupOfAuthorizableIndex;
continue outer;
}
}
i++;
}
}

private String deleteAuthorizable(Authorizable authorizable) throws RepositoryException {
String message;
try {
Authorizable authorizable = userManager.getAuthorizable(authorizableId);
if (authorizable != null) {
authorizable.remove();
message = "Deleted authorizable " + authorizableId + "\n";
} else {
message = "Could not delete authorizable '" + authorizableId + "' because it does not exist\n";
List<String> removedFromGroups = new ArrayList<String>();
Iterator<Group> declaredMemberOf = authorizable.declaredMemberOf();
while (declaredMemberOf.hasNext()) {
Group groupTheAuthorizableIsMemberOf = declaredMemberOf.next();
if (groupTheAuthorizableIsMemberOf.removeMember(authorizable)) {
removedFromGroups.add(groupTheAuthorizableIsMemberOf.getID());
}
}

authorizable.remove();
message = "Deleted authorizable '" + authorizable.getID() + "'"
+ (!removedFromGroups.isEmpty() ? " and removed it from groups: " + StringUtils.join(removedFromGroups, ", ")
: "")
+ "\n";

} catch (RepositoryException e) {
message = "Error while deleting authorizable '" + authorizableId + "': e=" + e;
LOG.warn("Error while deleting authorizable '" + authorizableId + "': e=" + e, e);
message = "Error while deleting authorizable '" + authorizable.getID() + "': e=" + e;
LOG.warn("Error while deleting authorizable '" + authorizable.getID() + "': e=" + e, e);
}

return message;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,16 @@ public void testRemoveUnmanagedPrincipalNamesAtPath() {

onlyManagedPrincipalNames = authorizablesConfig.removeUnmanagedPrincipalNamesAtPath("/content/dam/geometrixx", principalSet, null);
assertEquals(principalSet("testgroupAllManaged"), onlyManagedPrincipalNames);
}

@Test
public void testRemoveUnmanagedPrincipalNamesAtPathWithNoAutorizableBean() {
//We add a new non-existant name to remove but that doesn't belong in the authorizables list
Set<String> principalSet = principalSet(beanTestGroupAllManaged.getPrincipalName(), testgroupPartlyManaged.getPrincipalName(),
beanEveryone.getPrincipalName(), "nonExistentPrincipal");

Set<String> removedPrincipals = authorizablesConfig.removeUnmanagedPrincipalNamesAtPath("/content/dam/geometrixx", principalSet, null);
assertEquals(principalSet("testgroupAllManaged", "nonExistentPrincipal"), removedPrincipals);
}

@Test
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package biz.netcentric.cq.tools.actool.impl;

import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import javax.jcr.RepositoryException;

import org.apache.jackrabbit.api.security.user.Authorizable;
import org.apache.jackrabbit.api.security.user.Group;
import org.apache.jackrabbit.api.security.user.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.runners.MockitoJUnitRunner;
import org.mockito.stubbing.Answer;

@RunWith(MockitoJUnitRunner.class)
public class AcInstallationServiceImplTest {

AcInstallationServiceImpl acInstallationServiceImpl = new AcInstallationServiceImpl();

@Mock
Group group1;

@Mock
Group group2;

@Mock
Group group3;

@Mock
Group group4;

@Mock
Group group5;

@Mock
Group group6;

@Mock
Group group7;

@Mock
User user1;

@Mock
User user2;

@Test
public void testSortAuthorizablesForDeletion() throws RepositoryException {

when(group1.getID()).thenReturn("group1");
when(group2.getID()).thenReturn("group2");
when(group3.getID()).thenReturn("group3");
when(group4.getID()).thenReturn("group4");
when(group5.getID()).thenReturn("group5");
when(group6.getID()).thenReturn("group6");
when(group7.getID()).thenReturn("group7");
when(user1.getID()).thenReturn("user1");
when(user2.getID()).thenReturn("user2");

when(group4.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group3, group2));

when(user1.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group1, group5));

when(group1.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group4));

when(group5.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group1, group2, group3));

when(user2.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group2, group3));

when(group2.declaredMemberOf()).thenAnswer(GroupIteratorAnswer.forGroups(group3));


List<Authorizable> authsToDelete = Arrays.<Authorizable> asList(group1, group2, group3, group4, group5, group6, user1, user2);
acInstallationServiceImpl.sortAuthorizablesForDeletion(authsToDelete);

assertTrue(authsToDelete.indexOf(group4) < authsToDelete.indexOf(group3));
assertTrue(authsToDelete.indexOf(group4) < authsToDelete.indexOf(group2));

assertTrue(authsToDelete.indexOf(user1) < authsToDelete.indexOf(group1));
assertTrue(authsToDelete.indexOf(user1) < authsToDelete.indexOf(group5));

assertTrue(authsToDelete.indexOf(group1) < authsToDelete.indexOf(group4));

assertTrue(authsToDelete.indexOf(group5) < authsToDelete.indexOf(group1));
assertTrue(authsToDelete.indexOf(group5) < authsToDelete.indexOf(group2));
assertTrue(authsToDelete.indexOf(group5) < authsToDelete.indexOf(group3));

assertTrue(authsToDelete.indexOf(user2) < authsToDelete.indexOf(group2));
assertTrue(authsToDelete.indexOf(user2) < authsToDelete.indexOf(group3));

assertTrue(authsToDelete.indexOf(group2) < authsToDelete.indexOf(group3));

}

private static class GroupIteratorAnswer implements Answer<Iterator<Group>> {

static GroupIteratorAnswer forGroups(Group... groups) {
return new GroupIteratorAnswer(Arrays.asList(groups));
}

List<Group> groups;

public GroupIteratorAnswer(List<Group> groups) {
this.groups = groups;
}

@Override
public Iterator<Group> answer(InvocationOnMock invocation) throws Throwable {

return groups.iterator();
}
}
}
2 changes: 1 addition & 1 deletion accesscontroltool-exampleconfig-package/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>biz.netcentric.cq.tools.accesscontroltool</groupId>
<artifactId>accesscontroltool</artifactId>
<version>2.0.8</version>
<version>2.0.9</version>
</parent>

<!-- ====================================================================== -->
Expand Down
2 changes: 1 addition & 1 deletion accesscontroltool-oakindex-package/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>biz.netcentric.cq.tools.accesscontroltool</groupId>
<artifactId>accesscontroltool</artifactId>
<version>2.0.8</version>
<version>2.0.9</version>
</parent>

<!-- ====================================================================== -->
Expand Down
2 changes: 1 addition & 1 deletion accesscontroltool-package/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<parent>
<groupId>biz.netcentric.cq.tools.accesscontroltool</groupId>
<artifactId>accesscontroltool</artifactId>
<version>2.0.8</version>
<version>2.0.9</version>
</parent>

<!-- ====================================================================== -->
Expand Down
Loading

0 comments on commit d217131

Please sign in to comment.