diff --git a/README.md b/README.md index d9ec3f30..f40acea2 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ See also our talk at [AdaptTo 2016](https://adapt.to/2016/en/schedule/ac-tool.ht # Requirements -The AC Tool requires Java 7 and AEM 6.1 or above (use v1.x for older versions) +The AC Tool requires Java 7 and AEM 6.1 (SP1) or above (use v1.x for older versions) # Installation diff --git a/accesscontroltool-bundle/pom.xml b/accesscontroltool-bundle/pom.xml index 2eecb559..be61b31a 100644 --- a/accesscontroltool-bundle/pom.xml +++ b/accesscontroltool-bundle/pom.xml @@ -11,7 +11,7 @@ biz.netcentric.cq.tools.accesscontroltool accesscontroltool - 2.0.3 + 2.0.4 @@ -103,6 +103,10 @@ com.day.cq cq-commons + + com.adobe.granite + com.adobe.granite.crypto + org.yaml snakeyaml diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstaller.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstaller.java index 4c0275f9..8c9f3d11 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstaller.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstaller.java @@ -13,8 +13,9 @@ import javax.jcr.Session; +import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AceBean; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; /** Installs AceBeans to content paths. */ public interface AceBeanInstaller { @@ -28,7 +29,7 @@ public interface AceBeanInstaller { * @param installationLog the installation log * @param authorizablesToRemoveAcesFor * @param intermediateSaves whether the session should be saved after each path (for each ACL) */ - void installPathBasedACEs(final Map> pathBasedAceMapFromConfig, final Session session, - final AcInstallationLog installationLog, Set authorizablesToRemoveAcesFor, boolean intermediateSaves) throws Exception; + void installPathBasedACEs(final Map> pathBasedAceMapFromConfig, final AcConfiguration acConfiguration, final Session session, + final InstallationLogger installationLog, Set authorizablesToRemoveAcesFor, boolean intermediateSaves) throws Exception; } \ No newline at end of file diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerClassic.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerClassic.java index 8e234d57..98269e53 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerClassic.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerClassic.java @@ -40,7 +40,7 @@ import biz.netcentric.cq.tools.actool.configmodel.AceBean; import biz.netcentric.cq.tools.actool.helper.AccessControlUtils; import biz.netcentric.cq.tools.actool.helper.RestrictionsHolder; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; /** The way ACEs were installed in version one is still available and can be configured in "global_config" section by setting * "installAclsIncrementally=false". */ @@ -54,7 +54,7 @@ public class AceBeanInstallerClassic extends BaseAceBeanInstaller implements Ace * * @throws RepositoryException */ protected void installAcl(Set aceBeanSetFromConfig, String path, Set principalsToRemoveAcesFor, Session session, - AcInstallationLog installLog) throws RepositoryException { + InstallationLogger installLog) throws RepositoryException { // Remove all config contained authorizables from ACL of this path int countRemoved = AccessControlUtils.deleteAllEntriesForPrincipalsFromACL(session, @@ -80,7 +80,7 @@ protected void installAcl(Set aceBeanSetFromConfig, String path, Set actionMap = aceBean.getActionMap(); if (actionMap.isEmpty()) { return acl; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncremental.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncremental.java index 6b392f64..052ac407 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncremental.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncremental.java @@ -49,7 +49,7 @@ import biz.netcentric.cq.tools.actool.helper.AcHelper; import biz.netcentric.cq.tools.actool.helper.AccessControlUtils; import biz.netcentric.cq.tools.actool.helper.Constants; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; @Service @Component @@ -66,7 +66,7 @@ public class AceBeanInstallerIncremental extends BaseAceBeanInstaller implements * * @throws RepositoryException */ protected void installAcl(Set aceBeanSetFromConfig, String path, Set principalsInConfiguration, Session session, - AcInstallationLog installLog) throws RepositoryException { + InstallationLogger installLog) throws RepositoryException { boolean hadPendingChanges = session.hasPendingChanges(); @@ -210,7 +210,7 @@ protected JackrabbitAccessControlList getAccessControlList(AccessControlManager } private Set transformActionsIntoPrivileges(Set aceBeanSetFromConfig, Session session, - AcInstallationLog installLog) throws RepositoryException { + InstallationLogger installLog) throws RepositoryException { Set aceBeanSetWithPrivilegesOnly = new LinkedHashSet(); @@ -230,7 +230,7 @@ private Set transformActionsIntoPrivileges(Set aceBeanSetFromC } private Set getPrincipalAceBeansForActionAceBeanCached(AceBean origAceBean, Session session, - AcInstallationLog installLog) throws RepositoryException { + InstallationLogger installLog) throws RepositoryException { String cacheKey = (definesContent(origAceBean.getJcrPathForPolicyApi(), session) ? "definesContent" : "simple") + "-" + origAceBean.getPermission() + "-" + getRestrictionsComparable(origAceBean.getRestrictions()) + "-" diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java index eda155b5..d06385e2 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/aceinstaller/BaseAceBeanInstaller.java @@ -8,7 +8,7 @@ */ package biz.netcentric.cq.tools.actool.aceinstaller; -import static biz.netcentric.cq.tools.actool.history.AcInstallationLog.msHumanReadable; +import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable; import java.security.Principal; import java.util.Arrays; @@ -33,12 +33,13 @@ import org.slf4j.LoggerFactory; import biz.netcentric.cq.tools.actool.comparators.AcePermissionComparator; +import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AceBean; import biz.netcentric.cq.tools.actool.configmodel.Restriction; import biz.netcentric.cq.tools.actool.helper.AccessControlUtils; import biz.netcentric.cq.tools.actool.helper.ContentHelper; import biz.netcentric.cq.tools.actool.helper.RestrictionsHolder; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; /** Base Class */ public abstract class BaseAceBeanInstaller implements AceBeanInstaller { @@ -48,8 +49,9 @@ public abstract class BaseAceBeanInstaller implements AceBeanInstaller { @Override public void installPathBasedACEs( final Map> pathBasedAceMapFromConfig, + final AcConfiguration acConfiguration, final Session session, - final AcInstallationLog history, Set principalsToRemoveAcesFor, + final InstallationLogger history, Set principalsToRemoveAcesFor, boolean intermediateSaves) throws Exception { StopWatch stopWatch = new StopWatch(); @@ -86,7 +88,7 @@ public void installPathBasedACEs( new AcePermissionComparator()); orderedAceBeanSetFromConfig.addAll(aceBeanSetFromConfig); - Set principalsToRemoveAcesForAtThisPath = history.getAcConfiguration().getAuthorizablesConfig() + Set principalsToRemoveAcesForAtThisPath = acConfiguration.getAuthorizablesConfig() .removeUnmanagedPrincipalNamesAtPath(path, principalsToRemoveAcesFor); installAcl(orderedAceBeanSetFromConfig, path, principalsToRemoveAcesForAtThisPath, session, history); @@ -101,18 +103,18 @@ public void installPathBasedACEs( + " parent paths missing for creation of intial content (those paths were skipped, see verbose log for details)"); } - history.addMessage(LOG, "Finished installation of " + paths.size() + " ACLs in " - + msHumanReadable(stopWatch.getTime()) - + " (changed ACLs=" + history.getCountAclsChanged() + " unchanged ACLs=" + history.getCountAclsUnchanged() - + " path does not exist=" + history.getCountAclsPathDoesNotExist() + " action cache hit/miss=" + history.addMessage(LOG, "ACL Update Statistics: Changed=" + history.getCountAclsChanged() + " Unchanged=" + history.getCountAclsUnchanged() + + " Path not found=" + history.getCountAclsPathDoesNotExist() + " (action cache hit/miss=" + history.getCountActionCacheHit() + "/" + history.getCountActionCacheMiss() + ")"); + history.addMessage(LOG, "*** Finished installation of " + paths.size() + " ACLs in " + + msHumanReadable(stopWatch.getTime())); } /** Installs a full set of ACE beans that form an ACL for the path * * @throws RepositoryException */ protected abstract void installAcl(Set aceBeanSetFromConfig, String path, Set authorizablesToRemoveAcesFor, - Session session, AcInstallationLog history) throws RepositoryException; + Session session, InstallationLogger history) throws RepositoryException; protected boolean installPrivileges(AceBean aceBean, Principal principal, JackrabbitAccessControlList acl, Session session, diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/api/InstallationLog.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/api/InstallationLog.java index 5ed8f14b..3d4a6111 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/api/InstallationLog.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/api/InstallationLog.java @@ -10,14 +10,20 @@ import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo; +/** + * Access to log messages being emitted + * + */ public interface InstallationLog extends AcInstallationHistoryPojo { + // This is only set for the installhook mechanism String getCrxPackageName(); String getMessageHistory(); String getVerboseMessageHistory(); - + + // TODO: move to separate interface InstallationResult which extends this interface int getCountAclsUnchanged(); int getCountAclsChanged(); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/AuthorizableInstallerService.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/AuthorizableInstallerService.java index fa71ea57..5712c952 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/AuthorizableInstallerService.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/AuthorizableInstallerService.java @@ -11,13 +11,17 @@ import javax.jcr.RepositoryException; import javax.jcr.Session; +import com.adobe.granite.crypto.CryptoException; + +import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AuthorizablesConfig; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; public interface AuthorizableInstallerService { - public void installAuthorizables( - AuthorizablesConfig principalMapFromConfig, - final Session session, AcInstallationLog installLog) throws RepositoryException, AuthorizableCreatorException; - + void installAuthorizables( + AcConfiguration acConfiguration, + AuthorizablesConfig authorizablesConfigBeans, + final Session session, InstallationLogger installLog) + throws RepositoryException, AuthorizableCreatorException, CryptoException; } diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImpl.java index 8dd6626e..32af8267 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImpl.java @@ -37,15 +37,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.adobe.granite.crypto.CryptoException; +import com.adobe.granite.crypto.CryptoSupport; + import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableCreatorException; import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableInstallerService; +import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean; import biz.netcentric.cq.tools.actool.configmodel.AuthorizablesConfig; import biz.netcentric.cq.tools.actool.helper.AcHelper; import biz.netcentric.cq.tools.actool.helper.AccessControlUtils; import biz.netcentric.cq.tools.actool.helper.Constants; import biz.netcentric.cq.tools.actool.helper.ContentHelper; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; @Service @Component(metatype = true, label = "AC AuthorizableCreatorService", description = "Service that installs groups according to textual configuration files") @@ -65,16 +69,20 @@ public class AuthorizableInstallerServiceImpl implements @Reference(cardinality = ReferenceCardinality.OPTIONAL_UNARY) ExternalGroupInstallerServiceImpl externalGroupCreatorService; + @Reference + CryptoSupport cryptoSupport; + @Override public void installAuthorizables( + AcConfiguration acConfiguration, AuthorizablesConfig authorizablesConfigBeans, - final Session session, AcInstallationLog installLog) - throws RepositoryException, AuthorizableCreatorException { + final Session session, InstallationLogger installLog) + throws RepositoryException, AuthorizableCreatorException, CryptoException { Set authorizablesFromConfigurations = authorizablesConfigBeans.getAuthorizableIds(); for (AuthorizableConfigBean authorizableConfigBean : authorizablesConfigBeans) { - installAuthorizableConfigurationBean(session, + installAuthorizableConfigurationBean(session, acConfiguration, authorizableConfigBean, installLog, authorizablesFromConfigurations); } @@ -83,11 +91,12 @@ public void installAuthorizables( private void installAuthorizableConfigurationBean(final Session session, + AcConfiguration acConfiguration, AuthorizableConfigBean authorizableConfigBean, - AcInstallationLog installLog, Set authorizablesFromConfigurations) + InstallationLogger installLog, Set authorizablesFromConfigurations) throws AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException, - AuthorizableExistsException, AuthorizableCreatorException { + AuthorizableExistsException, AuthorizableCreatorException, CryptoException { String authorizableId = authorizableConfigBean.getAuthorizableId(); LOG.debug("- start installation of authorizable: {}", authorizableId); @@ -98,7 +107,7 @@ private void installAuthorizableConfigurationBean(final Session session, // if current authorizable from config doesn't exist yet Authorizable authorizableToInstall = userManager.getAuthorizable(authorizableId); if (authorizableToInstall == null) { - authorizableToInstall = createNewAuthorizable(authorizableConfigBean, installLog, userManager, session); + authorizableToInstall = createNewAuthorizable(acConfiguration, authorizableConfigBean, installLog, userManager, session); } // if current authorizable from config already exists in repository else { @@ -108,17 +117,17 @@ private void installAuthorizableConfigurationBean(final Session session, // update password for users if (!authorizableToInstall.isGroup() && !authorizableConfigBean.isSystemUser() && StringUtils.isNotBlank(authorizableConfigBean.getPassword())) { - ((User) authorizableToInstall).changePassword(authorizableConfigBean.getPassword()); + setUserPassword(authorizableConfigBean, (User) authorizableToInstall); } // move authorizable if path changed (retaining existing members) - handleRecreationOfAuthorizableIfNecessary(session, authorizableConfigBean, installLog, userManager); + handleRecreationOfAuthorizableIfNecessary(session, acConfiguration, authorizableConfigBean, installLog, userManager); - applyGroupMembershipConfigIsMemberOf(installLog, authorizableConfigBean, userManager, session, authorizablesFromConfigurations); + applyGroupMembershipConfigIsMemberOf(installLog, acConfiguration, authorizableConfigBean, userManager, session, authorizablesFromConfigurations); } - applyGroupMembershipConfigMembers(authorizableConfigBean, installLog, authorizableId, userManager, authorizablesFromConfigurations); + applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, installLog, authorizableId, userManager, authorizablesFromConfigurations); if (StringUtils.isNotBlank(authorizableConfigBean.getMigrateFrom()) && authorizableConfigBean.isGroup()) { migrateFromOldGroup(authorizableConfigBean, userManager, installLog); @@ -126,11 +135,21 @@ private void installAuthorizableConfigurationBean(final Session session, } + void setUserPassword(final AuthorizableConfigBean authorizableConfigBean, + final User authorizableToInstall) throws RepositoryException, CryptoException { + String password = authorizableConfigBean.getPassword(); + if (password.matches("\\{.+}")) { + password = cryptoSupport.unprotect(password); + } + authorizableToInstall.changePassword(password); + } + + /** This is only relevant for members that point to groups/users not contained in configuration. * {@link biz.netcentric.cq.tools.actool.configreader.YamlConfigurationMerger#ensureIsMemberOfIsUsedWherePossible()} ensures that * regular relationships between groups contained in config are kept in isMemberOf */ @SuppressWarnings("unchecked") - void applyGroupMembershipConfigMembers(AuthorizableConfigBean authorizableConfigBean, AcInstallationLog installLog, + void applyGroupMembershipConfigMembers(AcConfiguration acConfiguration, AuthorizableConfigBean authorizableConfigBean, InstallationLogger installLog, String principalId, UserManager userManager, Set authorizablesFromConfigurations) throws RepositoryException { if (authorizableConfigBean.isGroup()) { String[] membersInConfigArr = authorizableConfigBean.getMembers(); @@ -146,7 +165,7 @@ void applyGroupMembershipConfigMembers(AuthorizableConfigBean authorizableConfig // ensure regular users are never removed relevantMembersInRepo = removeRegularUsers(relevantMembersInRepo, userManager); // take configuration 'defaultUnmanagedExternalMembersRegex' into account (and remove matching groups from further handling) - relevantMembersInRepo = removeExternalMembersUnmanagedByConfiguration(authorizableConfigBean, relevantMembersInRepo, + relevantMembersInRepo = removeExternalMembersUnmanagedByConfiguration(acConfiguration, authorizableConfigBean, relevantMembersInRepo, installLog); Set membersToAdd = new HashSet(CollectionUtils.subtract(membersInConfig, relevantMembersInRepo)); @@ -202,10 +221,10 @@ private Set removeRegularUsers(Set allMembersFromRepo, UserManag return relevantMembers; } - private Set removeExternalMembersUnmanagedByConfiguration(AuthorizableConfigBean authorizableConfigBean, - Set relevantMembersInRepo, AcInstallationLog installLog) { + private Set removeExternalMembersUnmanagedByConfiguration(AcConfiguration acConfiguration, AuthorizableConfigBean authorizableConfigBean, + Set relevantMembersInRepo, InstallationLogger installLog) { Set relevantMembers = new HashSet(relevantMembersInRepo); - Pattern unmanagedExternalMembersRegex = installLog.getAcConfiguration().getGlobalConfiguration() + Pattern unmanagedExternalMembersRegex = acConfiguration.getGlobalConfiguration() .getDefaultUnmanagedExternalMembersRegex(); Set unmanagedMembers = new HashSet(); @@ -240,7 +259,7 @@ private Set getDeclaredMembers(Group installedGroup) throws RepositoryEx } private void migrateFromOldGroup(AuthorizableConfigBean authorizableConfigBean, UserManager userManager, - AcInstallationLog installLog) throws RepositoryException { + InstallationLogger installLog) throws RepositoryException { Authorizable groupForMigration = userManager.getAuthorizable(authorizableConfigBean.getMigrateFrom()); String authorizableId = authorizableConfigBean.getAuthorizableId(); @@ -284,8 +303,9 @@ private void migrateFromOldGroup(AuthorizableConfigBean authorizableConfigBean, } private void handleRecreationOfAuthorizableIfNecessary(final Session session, + AcConfiguration acConfiguration, AuthorizableConfigBean principalConfigBean, - AcInstallationLog installLog, + InstallationLogger installLog, UserManager userManager) throws RepositoryException, AuthorizableCreatorException { String authorizableId = principalConfigBean.getAuthorizableId(); @@ -341,7 +361,7 @@ private void handleRecreationOfAuthorizableIfNecessary(final Session session, existingAuthorizable.remove(); // create group again using values form config - Authorizable newAuthorizable = createNewAuthorizable(principalConfigBean, installLog, userManager, session); + Authorizable newAuthorizable = createNewAuthorizable(acConfiguration, principalConfigBean, installLog, userManager, session); int countMovedMembersOfGroup = 0; if (newAuthorizable.isGroup()) { @@ -388,7 +408,8 @@ private void deleteOldIntermediatePath(final Session session, } } - private void applyGroupMembershipConfigIsMemberOf(AcInstallationLog installLog, + private void applyGroupMembershipConfigIsMemberOf(InstallationLogger installLog, + AcConfiguration acConfiguration, AuthorizableConfigBean authorizableConfigBean, UserManager userManager, Session session, Set authorizablesFromConfigurations) throws RepositoryException, AuthorizableCreatorException { String[] memberOf = authorizableConfigBean.getMemberOf(); @@ -398,13 +419,14 @@ private void applyGroupMembershipConfigIsMemberOf(AcInstallationLog installLog, Set membershipGroupsFromConfig = getMembershipGroupsFromConfig(memberOf); Set membershipGroupsFromRepository = getMembershipGroupsFromRepository(currentGroupFromRepository); - applyGroupMembershipConfigIsMemberOf(authorizableId, installLog, userManager, session, membershipGroupsFromConfig, + applyGroupMembershipConfigIsMemberOf(authorizableId, acConfiguration, installLog, userManager, session, membershipGroupsFromConfig, membershipGroupsFromRepository, authorizablesFromConfigurations); } private Authorizable createNewAuthorizable( + AcConfiguration acConfiguration, AuthorizableConfigBean principalConfigBean, - AcInstallationLog installLog, + InstallationLogger installLog, UserManager userManager, Session session) throws AuthorizableExistsException, RepositoryException, AuthorizableCreatorException { @@ -415,7 +437,7 @@ private Authorizable createNewAuthorizable( Authorizable newAuthorizable = null; if (isGroup) { - newAuthorizable = createNewGroup(userManager, principalConfigBean, installLog, session); + newAuthorizable = createNewGroup(userManager, acConfiguration.getAuthorizablesConfig(), principalConfigBean, installLog, session); LOG.info("Successfully created new group: {}", authorizableId); } else { if (StringUtils.isNotEmpty(principalConfigBean.getExternalId())) { @@ -424,7 +446,7 @@ private Authorizable createNewAuthorizable( + "') - use a ootb sync handler to have users automatically created."); } - newAuthorizable = createNewUser(userManager, principalConfigBean, installLog, session); + newAuthorizable = createNewUser(userManager, acConfiguration.getAuthorizablesConfig(), principalConfigBean, installLog, session); LOG.info("Successfully created new user: {}", authorizableId); } @@ -458,7 +480,8 @@ private Set getMembershipGroupsFromConfig(String[] memberOf) { @SuppressWarnings("unchecked") void applyGroupMembershipConfigIsMemberOf(String authorizableId, - AcInstallationLog installLog, UserManager userManager, Session session, + AcConfiguration acConfiguration, + InstallationLogger installLog, UserManager userManager, Session session, Set membershipGroupsFromConfig, Set membershipGroupsFromRepository, Set authorizablesFromConfigurations) throws RepositoryException, AuthorizableExistsException, @@ -471,7 +494,7 @@ void applyGroupMembershipConfigIsMemberOf(String authorizableId, installLog.addVerboseMessage(LOG, "Authorizable " + authorizableId + " isMemberOf(repo)=" + membershipGroupsFromRepository); installLog.addVerboseMessage(LOG, "Authorizable " + authorizableId + " isMemberOf(conifg)=" + membershipGroupsFromConfig); - Set validatedMembershipGroupsFromConfig = validateAssignedGroups(userManager, session, authorizableId, + Set validatedMembershipGroupsFromConfig = validateAssignedGroups(userManager, acConfiguration.getAuthorizablesConfig(), session, authorizableId, membershipGroupsFromConfig, installLog); Collection unChangedMembers = CollectionUtils.intersection(membershipGroupsFromRepository, @@ -485,7 +508,7 @@ void applyGroupMembershipConfigIsMemberOf(String authorizableId, validatedMembershipGroupsFromConfig); Set unmanagedMembers = new HashSet(); - Pattern unmanagedExternalIsMemberOfRegex = installLog.getAcConfiguration().getGlobalConfiguration() + Pattern unmanagedExternalIsMemberOfRegex = acConfiguration.getGlobalConfiguration() .getDefaultUnmanagedExternalIsMemberOfRegex(); Iterator toBeRemovedMembersIt = toBeRemovedMembers.iterator(); @@ -532,8 +555,9 @@ void applyGroupMembershipConfigIsMemberOf(String authorizableId, private Authorizable createNewGroup( final UserManager userManager, + AuthorizablesConfig authorizablesConfig, AuthorizableConfigBean principalConfigBean, - AcInstallationLog installLog, Session session) + InstallationLogger installLog, Session session) throws AuthorizableExistsException, RepositoryException, AuthorizableCreatorException { @@ -567,14 +591,14 @@ private Authorizable createNewGroup( newGroup = (Group) userManager.getAuthorizable(groupID); } - addMembersToReferencingAuthorizables(newGroup, principalConfigBean, userManager, session, installLog); + addMembersToReferencingAuthorizables(newGroup, authorizablesConfig, principalConfigBean, userManager, session, installLog); setAuthorizableProperties(newGroup, principalConfigBean, session, installLog); return newGroup; } void setAuthorizableProperties(Authorizable authorizable, AuthorizableConfigBean principalConfigBean, - Session session, AcInstallationLog installationLog) + Session session, InstallationLogger installationLog) throws RepositoryException { String profileContent = principalConfigBean.getProfileContent(); @@ -639,8 +663,9 @@ void setAuthorizableProperties(Authorizable authorizable, AuthorizableConfigBean private Authorizable createNewUser( final UserManager userManager, + AuthorizablesConfig authorizablesConfig, AuthorizableConfigBean principalConfigBean, - AcInstallationLog installLog, + InstallationLogger installLog, Session session) throws AuthorizableExistsException, RepositoryException, AuthorizableCreatorException { @@ -662,19 +687,19 @@ private Authorizable createNewUser( } setAuthorizableProperties(newUser, principalConfigBean, session, installLog); - addMembersToReferencingAuthorizables(newUser, principalConfigBean, userManager, session, installLog); + addMembersToReferencingAuthorizables(newUser, authorizablesConfig, principalConfigBean, userManager, session, installLog); return newUser; } - private void addMembersToReferencingAuthorizables(Authorizable authorizable, AuthorizableConfigBean principalConfigBean, - final UserManager userManager, Session session, AcInstallationLog installLog) + private void addMembersToReferencingAuthorizables(Authorizable authorizable, AuthorizablesConfig authorizablesConfig, AuthorizableConfigBean principalConfigBean, + final UserManager userManager, Session session, InstallationLogger installLog) throws RepositoryException, AuthorizableCreatorException { String authorizableId = principalConfigBean.getAuthorizableId(); String[] memberOf = principalConfigBean.getMemberOf(); if ((authorizable != null) && (memberOf != null) && (memberOf.length > 0)) { // add group to groups according to configuration - Set referencingAuthorizablesToBeChanged = validateAssignedGroups(userManager, session, authorizableId, + Set referencingAuthorizablesToBeChanged = validateAssignedGroups(userManager, authorizablesConfig, session, authorizableId, new HashSet(Arrays.asList(memberOf)), installLog); if (!referencingAuthorizablesToBeChanged.isEmpty()) { LOG.debug("start adding {} to assignedGroups", authorizableId); @@ -700,8 +725,8 @@ private void addMembersToReferencingAuthorizables(Authorizable authorizable, Aut * @throws RepositoryException * @throws AuthorizableCreatorException if one of the authorizables contained in membersOf array is a user */ Set validateAssignedGroups( - final UserManager userManager, Session session, final String authorizablelId, - final Set isMemberOf, AcInstallationLog installLog) throws RepositoryException, + final UserManager userManager, AuthorizablesConfig authorizablesConfig, Session session, final String authorizablelId, + final Set isMemberOf, InstallationLogger installLog) throws RepositoryException, AuthorizableCreatorException { Set authorizableSet = new HashSet(); @@ -733,13 +758,13 @@ Set validateAssignedGroups( // check if authorizable is contained in any of the // configurations - AuthorizableConfigBean configBeanForIsMemberOf = installLog.getAcConfiguration().getAuthorizablesConfig() + AuthorizableConfigBean configBeanForIsMemberOf = authorizablesConfig .getAuthorizableConfig(memberOfAuthorizable); if (configBeanForIsMemberOf != null) { - Group newGroup = (Group) createNewGroup(userManager, configBeanForIsMemberOf, installLog, session); + Group newGroup = (Group) createNewGroup(userManager, authorizablesConfig, configBeanForIsMemberOf, installLog, session); authorizableSet.add(newGroup.getID()); LOG.info("Created group to be able to add {} to group {} ", authorizablelId, memberOfAuthorizable); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/ExternalGroupInstallerServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/ExternalGroupInstallerServiceImpl.java index 1286ec8f..195d5d04 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/ExternalGroupInstallerServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/ExternalGroupInstallerServiceImpl.java @@ -33,6 +33,7 @@ import biz.netcentric.cq.tools.actool.authorizableinstaller.AuthorizableCreatorException; import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean; import biz.netcentric.cq.tools.actool.helper.Constants; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo; /** SCR component to create external groups (as configured using "externalId"). Only available if package @@ -50,7 +51,7 @@ public class ExternalGroupInstallerServiceImpl { public Authorizable createGroupWithExternalId( final UserManager userManager, final AuthorizableConfigBean authorizableConfigBean, - AcInstallationHistoryPojo status, + InstallationLogger status, Session session) throws AuthorizableExistsException, RepositoryException, AuthorizableCreatorException { diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigurationMerger.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigurationMerger.java index 56a23ecb..0f80f9bc 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigurationMerger.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/ConfigurationMerger.java @@ -14,7 +14,7 @@ import javax.jcr.Session; import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; import biz.netcentric.cq.tools.actool.validators.exceptions.AcConfigBeanValidationException; public interface ConfigurationMerger { @@ -31,7 +31,7 @@ public interface ConfigurationMerger { * @throws AcConfigBeanValidationException in case the given configuration is invalid */ public abstract AcConfiguration getMergedConfigurations( final Map newestConfigurations, - final AcInstallationLog installationLog, + final PersistableInstallationLogger installationLog, final ConfigReader configReader, Session session) throws RepositoryException, AcConfigBeanValidationException; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMerger.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMerger.java index c714e5ec..ee180763 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMerger.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMerger.java @@ -8,7 +8,7 @@ */ package biz.netcentric.cq.tools.actool.configreader; -import static biz.netcentric.cq.tools.actool.history.AcInstallationLog.msHumanReadable; +import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable; import java.util.ArrayList; import java.util.Arrays; @@ -38,7 +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.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; import biz.netcentric.cq.tools.actool.validators.AceBeanValidator; import biz.netcentric.cq.tools.actool.validators.AuthorizableValidator; import biz.netcentric.cq.tools.actool.validators.ConfigurationsValidator; @@ -64,7 +65,7 @@ public class YamlConfigurationMerger implements ConfigurationMerger { @Override public AcConfiguration getMergedConfigurations( final Map configFileContentByFilename, - final AcInstallationLog history, + final PersistableInstallationLogger history, final ConfigReader configReader, Session session) throws RepositoryException, AcConfigBeanValidationException { @@ -179,7 +180,7 @@ public AcConfiguration getMergedConfigurations( } void ensureIsMemberOfIsUsedWherePossible(AuthorizablesConfig mergedAuthorizablesBeansfromConfig, - AcInstallationLog history) { + InstallationLogger history) { for (AuthorizableConfigBean group : mergedAuthorizablesBeansfromConfig) { if (!group.isGroup()) { diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProvider.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProvider.java index b8fee58e..55f914ed 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProvider.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProvider.java @@ -12,13 +12,13 @@ import javax.jcr.Session; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; /** Provides the objects for . * * @author ghenzler */ public interface YamlMacroChildNodeObjectsProvider { - List getValuesForPath(String pathOfChildrenOfClause, AcInstallationLog history, Session session); + List getValuesForPath(String pathOfChildrenOfClause, InstallationLogger history, Session session); } \ No newline at end of file diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProviderImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProviderImpl.java index a87e2103..6f9ee85e 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProviderImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroChildNodeObjectsProviderImpl.java @@ -33,7 +33,7 @@ import com.day.cq.commons.jcr.JcrConstants; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; @Service @Component @@ -45,7 +45,7 @@ public class YamlMacroChildNodeObjectsProviderImpl implements YamlMacroChildNode private SlingRepository repository; @Override - public List getValuesForPath(String pathOfChildrenOfClause, AcInstallationLog history, Session session) { + public List getValuesForPath(String pathOfChildrenOfClause, InstallationLogger history, Session session) { LOG.debug("FOR Loop: Getting children for " + pathOfChildrenOfClause); @@ -112,7 +112,7 @@ public List getValuesForPath(String pathOfChildrenOfClause, AcInstallati throw new IllegalStateException("Could not get children of path " + pathOfChildrenOfClause + ": " + e, e); } - history.addMessage(LOG, "Loop for children of " + pathOfChildrenOfClause + " evaluates to " + results.size() + " children"); + history.addVerboseMessage(LOG, "Loop for children of " + pathOfChildrenOfClause + " evaluates to " + results.size() + " children"); return results; } diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessor.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessor.java index 6d55fbcb..9548fa54 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessor.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessor.java @@ -13,13 +13,13 @@ import javax.jcr.Session; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; /** Processes FOR and IF statements in yaml files. * * @author ghenzler */ public interface YamlMacroProcessor { - List processMacros(List yamlList, AcInstallationLog history, Session session); + List processMacros(List yamlList, InstallationLogger history, Session session); } \ No newline at end of file diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorImpl.java index 899d8db1..d070dda4 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorImpl.java @@ -27,7 +27,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; @Service @Component @@ -51,15 +51,15 @@ public class YamlMacroProcessorImpl implements YamlMacroProcessor { YamlMacroChildNodeObjectsProvider yamlMacroChildNodeObjectsProvider; @Override - public List processMacros(List yamlList, AcInstallationLog installLog, Session session) { + public List processMacros(List yamlList, InstallationLogger installLog, Session session) { return (List) transform(yamlList, installLog, session); } - private Object transform(Object o, AcInstallationLog installLog, Session session) { + private Object transform(Object o, InstallationLogger installLog, Session session) { return transform(o, new HashMap(), installLog, session); } - private Object transform(Object o, Map variables, AcInstallationLog installLog, Session session) { + private Object transform(Object o, Map variables, InstallationLogger installLog, Session session) { if (o == null) { return null; } else if (o instanceof String) { @@ -143,7 +143,7 @@ private Object evaluateDefStatement(Map variables, Matcher varia } private Object evaluateForStatement(Map variables, Object objVal, Matcher forMatcher, - AcInstallationLog installLog, Session session) { + InstallationLogger installLog, Session session) { String varName = StringUtils.trim(forMatcher.group(1)); String valueOfInClause = StringUtils.trim(forMatcher.group(2)); String pathOfChildrenOfClause = StringUtils.trim(forMatcher.group(3)); @@ -168,7 +168,7 @@ private Object evaluateForStatement(Map variables, Object objVal } private Object evaluateIfStatement(Map variables, Object objVal, Matcher ifMatcher, - AcInstallationLog installLog, Session session) { + InstallationLogger installLog, Session session) { String condition = ifMatcher.group(1).trim(); boolean expressionIsTrue = elEvaluator.evaluateEl(condition, Boolean.class, variables); @@ -194,7 +194,7 @@ private void addToListWithPotentialUnfolding(List transformedList, Object transf } private List unfoldLoop(Map variables, Object val, String varName, List varValues, - AcInstallationLog installLog, Session session) { + InstallationLogger installLog, Session session) { List resultList = new ToBeUnfoldedList(); for (Object varValue : varValues) { @@ -207,7 +207,7 @@ private List unfoldLoop(Map variables, Object val, String varNam } private List unfoldIf(Map variables, Object val, boolean expressionIsTrue, - AcInstallationLog installLog, Session session) { + InstallationLogger installLog, Session session) { List resultList = new ToBeUnfoldedList(); if (expressionIsTrue) { unfold(val, resultList, variables, installLog, session); @@ -217,7 +217,7 @@ private List unfoldIf(Map variables, Object val, boolean express } private void unfold(Object val, List resultList, Map variablesAtThisScope, - AcInstallationLog installLog, Session session) { + InstallationLogger installLog, Session session) { if (val instanceof List) { List origList = (List) val; for (Object origListItem : origList) { diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/ContentHelper.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/ContentHelper.java index ef4beb19..41fc820a 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/ContentHelper.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/ContentHelper.java @@ -47,8 +47,7 @@ import org.slf4j.LoggerFactory; import biz.netcentric.cq.tools.actool.configmodel.AceBean; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; -import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; public class ContentHelper { public static final Logger LOG = LoggerFactory.getLogger(ContentHelper.class); @@ -56,7 +55,7 @@ public class ContentHelper { private ContentHelper() { } - public static boolean createInitialContent(final Session session, final AcInstallationLog history, String path, + public static boolean createInitialContent(final Session session, final InstallationLogger history, String path, Set aceBeanSetFromConfig) throws RepositoryException, PathNotFoundException, ItemExistsException, ConstraintViolationException, VersionException, InvalidSerializedDataException, LockException, AccessDeniedException { @@ -86,7 +85,7 @@ public static boolean createInitialContent(final Session session, final AcInstal } } - private static String findInitialContentInConfigsForPath(Set aceBeanSetFromConfig, AcInstallationHistoryPojo history) { + private static String findInitialContentInConfigsForPath(Set aceBeanSetFromConfig, InstallationLogger history) { String initialContent = null; for (AceBean aceBean : aceBeanSetFromConfig) { String currentInitialContent = aceBean.getInitialContent(); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/PurgeHelper.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/PurgeHelper.java index e0d522b5..2e8b3df0 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/PurgeHelper.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/PurgeHelper.java @@ -8,7 +8,7 @@ */ package biz.netcentric.cq.tools.actool.helper; -import static biz.netcentric.cq.tools.actool.history.AcInstallationLog.msHumanReadable; +import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable; import java.util.Iterator; import java.util.Set; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java index e97f4706..5e0b88b5 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java @@ -8,7 +8,7 @@ */ package biz.netcentric.cq.tools.actool.helper; -import static biz.netcentric.cq.tools.actool.history.AcInstallationLog.msHumanReadable; +import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable; import java.util.ArrayList; import java.util.HashSet; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcHistoryService.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcHistoryService.java index 61e40f92..16e8104f 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcHistoryService.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcHistoryService.java @@ -12,9 +12,9 @@ public interface AcHistoryService { - public void persistHistory(AcInstallationLog history); + public void persistHistory(PersistableInstallationLogger history); - public void persistAcePurgeHistory(AcInstallationLog history); + public void persistAcePurgeHistory(PersistableInstallationLogger history); public String[] getInstallationLogPaths(); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/InstallationLogger.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/InstallationLogger.java new file mode 100644 index 00000000..c5a647a2 --- /dev/null +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/InstallationLogger.java @@ -0,0 +1,43 @@ +package biz.netcentric.cq.tools.actool.history; + +import org.slf4j.Logger; + +import biz.netcentric.cq.tools.actool.api.InstallationLog; +/** + * This is the SPI for writing to the logs. + */ +// TODO: remove extends Installation log to completely separate writing from reading +public interface InstallationLogger extends InstallationLog { + + void addVerboseMessage(Logger log, String message); + + void addError(final String error); + + void addError(Logger log, String error); + + void addError(String error, Throwable e); + + void addError(Logger log, String error, Throwable e); + + void addMessage(Logger log, String message); + + void addWarning(Logger log, String warning); + + // all the following methods just modify some internal statistics + // TODO: move to dedicate interface + void incMissingParentPathsForInitialContent(); + + int getMissingParentPathsForInitialContent(); + + void incCountActionCacheHit(); + + void incCountActionCacheMiss(); + + void incCountAclsPathDoesNotExist(); + + void incCountAclsChanged(); + + void incCountAclsNoChange(); + + +} diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcInstallationLog.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/PersistableInstallationLogger.java similarity index 76% rename from accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcInstallationLog.java rename to accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/PersistableInstallationLogger.java index 7e125852..4f84a77c 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/AcInstallationLog.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/PersistableInstallationLogger.java @@ -23,13 +23,12 @@ import biz.netcentric.cq.tools.actool.api.InstallationLog; import biz.netcentric.cq.tools.actool.comparators.HistoryEntryComparator; -import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo; -public class AcInstallationLog implements InstallationLog, AcInstallationHistoryPojo { +public class PersistableInstallationLogger implements InstallationLogger, InstallationLog, AcInstallationHistoryPojo { - private static final String MSG_IDENTIFIER_EXCEPTION = "EXCEPTION:"; - private static final String MSG_IDENTIFIER_WARNING = "WARNING:"; + protected static final String MSG_IDENTIFIER_ERROR = "ERROR: "; + protected static final String MSG_IDENTIFIER_WARNING = "WARNING: "; private Set warnings = new HashSet(); private Set messages = new HashSet(); @@ -38,13 +37,11 @@ public class AcInstallationLog implements InstallationLog, AcInstallationHistory private Set verboseMessages = new HashSet(); private boolean success = true; - private Date installationDate; + private final Date installationDate; private long executionTime; private long msgIndex = 0; - Rendition rendition; private String mergedAndProcessedConfig; - private AcConfiguration acConfiguration; private Map configFileContentsByName; @@ -62,28 +59,14 @@ public class AcInstallationLog implements InstallationLog, AcInstallationHistory private DateFormat timestampFormat = new SimpleDateFormat("HH:mm:ss.SSS"); - public enum Rendition { - HTML, TXT; - } - - public AcInstallationLog() { - rendition = Rendition.TXT; - setInstallationDate(new Date()); - } - - public AcInstallationLog(Rendition rendition) { - this.rendition = rendition; - setInstallationDate(new Date()); + public PersistableInstallationLogger() { + installationDate = new Date(); } public Date getInstallationDate() { return installationDate; } - public void setInstallationDate(final Date installationDate) { - this.installationDate = installationDate; - } - public long getExecutionTime() { return executionTime; } @@ -105,14 +88,6 @@ public void setMergedAndProcessedConfig(String mergedAndProcessedConfig) { this.mergedAndProcessedConfig = mergedAndProcessedConfig; } - public AcConfiguration getAcConfiguration() { - return acConfiguration; - } - - public void setAcConfiguration(AcConfiguration acConfiguration) { - this.acConfiguration = acConfiguration; - } - public Map getConfigFileContentsByName() { return configFileContentsByName; } @@ -133,66 +108,61 @@ public void setCrxPackageName(String crxPackageName) { this.crxPackageName = crxPackageName; } + @Override public void addWarning(Logger log, String warning) { log.warn(warning); addWarning(warning); } - private void addWarning(String warning) { - if (rendition.equals(Rendition.HTML)) { - warnings.add(new HistoryEntry(msgIndex, new Timestamp( - new Date().getTime()), "" - + MSG_IDENTIFIER_WARNING + " " + warning + "")); - } else if (rendition.equals(Rendition.TXT)) { - warnings.add(new HistoryEntry(msgIndex, new Timestamp( - new Date().getTime()), MSG_IDENTIFIER_WARNING + " " - + warning)); - } + protected void addWarning(String warning) { + warnings.add(new HistoryEntry(msgIndex, new Timestamp( + new Date().getTime()), MSG_IDENTIFIER_WARNING + warning)); msgIndex++; } + @Override public void addMessage(Logger log, String message) { log.info(message); addMessage(message); } - private void addMessage(String message) { + protected void addMessage(String message) { messages.add(new HistoryEntry(msgIndex, new Timestamp(new Date() .getTime()), " " + message)); msgIndex++; } + @Override public void addError(Logger log, String error, Throwable e) { log.error(error, e); - addError(error + " / e=" + e); + addError(error, e); } + + @Override public void addError(Logger log, String error) { log.error(error); addError(error); } - public void addError(final String error) { - if (rendition.equals(Rendition.HTML)) { - errors.add(new HistoryEntry(msgIndex, new Timestamp( - new Date().getTime()), "" - + MSG_IDENTIFIER_EXCEPTION + "" + " " + error - + "")); - } else if (rendition.equals(Rendition.TXT)) { - errors.add(new HistoryEntry(msgIndex, new Timestamp( - new Date().getTime()), MSG_IDENTIFIER_EXCEPTION + " " - + error)); + public void addError(final String error, Throwable e) { + addError(error + " / e=" + e); + } - } + @Override + public void addError(final String error) { + errors.add(new HistoryEntry(msgIndex, new Timestamp( + new Date().getTime()), MSG_IDENTIFIER_ERROR + error)); success = false; msgIndex++; } + @Override public void addVerboseMessage(Logger log, String message) { log.debug(message); addVerboseMessage(message); } - private void addVerboseMessage(String message) { + protected void addVerboseMessage(String message) { verboseMessages.add(new HistoryEntry(msgIndex, new Timestamp( new Date().getTime()), " " + message)); msgIndex++; @@ -218,25 +188,12 @@ public void setSuccess(final boolean success) { public String toString() { StringBuilder sb = new StringBuilder(); - sb.append("\n" + "Installation triggered: " - + installationDate.toString() + "\n"); - sb.append("\n" + getMessageHistory() + "\n"); sb.append("\n" + "Execution time: " + msHumanReadable(executionTime) + "\n"); - if (rendition.equals(Rendition.HTML)) { - if (success) { - sb.append(HtmlConstants.FONT_COLOR_SUCCESS_HTML_OPEN); - } else { - sb.append(HtmlConstants.FONT_COLOR_NO_SUCCESS_HTML_OPEN); - } - } sb.append("\n" + "Success: " + success); - if (rendition.equals(Rendition.HTML)) { - sb.append(HtmlConstants.FONT_COLOR_SUCCESS_HTML_CLOSE); - } return sb.toString(); } @@ -310,6 +267,7 @@ public static String msHumanReadable(final long millis) { return result; } + @Override public void incCountAclsNoChange() { countAclsNoChange++; } @@ -322,6 +280,7 @@ public int getCountAclsUnchanged() { return countAclsNoChange; } + @Override public void incCountAclsChanged() { countAclsChanged++; } @@ -334,6 +293,7 @@ public int getCountAclsChanged() { return countAclsChanged; } + @Override public void incCountAclsPathDoesNotExist() { countAclsPathDoesNotExist++; } @@ -346,6 +306,7 @@ public int getCountAclsPathDoesNotExist() { return countAclsPathDoesNotExist; } + @Override public void incCountActionCacheMiss() { countActionCacheMiss++; } @@ -358,6 +319,7 @@ public int getCountActionCacheMiss() { return countActionCacheMiss; } + @Override public void incCountActionCacheHit() { countActionCacheHit++; } @@ -370,6 +332,7 @@ public int getCountActionCacheHit() { return countActionCacheHit; } + @Override public void incMissingParentPathsForInitialContent() { missingParentPathsForInitialContent++; } @@ -384,4 +347,5 @@ public int getMissingParentPathsForInitialContent() { return missingParentPathsForInitialContent; } + } diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/ProgressTrackerListenerInstallationLogger.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/ProgressTrackerListenerInstallationLogger.java new file mode 100644 index 00000000..1467ac40 --- /dev/null +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/ProgressTrackerListenerInstallationLogger.java @@ -0,0 +1,51 @@ +package biz.netcentric.cq.tools.actool.history; + +import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener; +import org.apache.jackrabbit.vault.packaging.PackageException; + +public class ProgressTrackerListenerInstallationLogger extends PersistableInstallationLogger { + + private final ProgressTrackerListener listener; + + public ProgressTrackerListenerInstallationLogger(ProgressTrackerListener listener) { + super(); + this.listener = listener; + } + + @Override + protected void addWarning(String warning) { + listener.onMessage(ProgressTrackerListener.Mode.TEXT, MSG_IDENTIFIER_WARNING + warning, ""); + super.addWarning(warning); + } + + @Override + protected void addMessage(String message) { + listener.onMessage(ProgressTrackerListener.Mode.TEXT, message, ""); + super.addMessage(message); + } + + @Override + public void addError(String error) { + listener.onError(ProgressTrackerListener.Mode.TEXT, MSG_IDENTIFIER_ERROR + error, null); + super.addError(error); + } + + @Override + public void addError(String error, Throwable t) { + Exception e; + if (t instanceof Exception) { + e = (Exception) t; + } else { + e = new PackageException("Unexpected low-level error during AC Tool installation: " + t.getMessage(), t); + } + listener.onError(ProgressTrackerListener.Mode.TEXT, error, e); + super.addError(error, e); + } + + @Override + protected void addVerboseMessage(String message) { + // no logging of verbose log in installation log (verbose log can be looked up via JMX) + super.addVerboseMessage(message); + } + +} diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/AcHistoryServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/AcHistoryServiceImpl.java index 10670711..fe356453 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/AcHistoryServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/AcHistoryServiceImpl.java @@ -37,7 +37,7 @@ import biz.netcentric.cq.tools.actool.comparators.TimestampPropertyComparator; import biz.netcentric.cq.tools.actool.helper.Constants; import biz.netcentric.cq.tools.actool.history.AcHistoryService; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; @Service @Component(metatype = true, label = "AC History Service", immediate = true, description = "Service that writes & fetches Ac installation histories") @@ -66,7 +66,7 @@ public void activate(@SuppressWarnings("rawtypes") final Map properties) } @Override - public void persistHistory(AcInstallationLog installLog) { + public void persistHistory(PersistableInstallationLogger installLog) { if (nrOfSavedHistories == 0) { installLog.addVerboseMessage(LOG, "History hasn't been persisted, configured number of histories is " + nrOfSavedHistories); @@ -156,7 +156,7 @@ public String getLastInstallationHistory() { return history; } - private void persistInstalledConfigurations(final Session session, final Node historyNode, AcInstallationLog installLog) { + private void persistInstalledConfigurations(final Session session, final Node historyNode, PersistableInstallationLogger installLog) { try { Map configFileContentsByName = installLog.getConfigFileContentsByName(); @@ -215,7 +215,7 @@ public String showHistory(int n) { } @Override - public void persistAcePurgeHistory(AcInstallationLog installLog) { + public void persistAcePurgeHistory(PersistableInstallationLogger installLog) { Session session = null; try { @@ -244,7 +244,7 @@ public void persistAcePurgeHistory(AcInstallationLog installLog) { } private static Node persistPurgeAceHistory(final Session session, - AcInstallationLog installLog, final Node historyNode) + PersistableInstallationLogger installLog, final Node historyNode) throws RepositoryException { Node purgeHistoryNode = historyNode.addNode( diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java index f59c96d7..2aec2da2 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/history/impl/HistoryUtils.java @@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory; import biz.netcentric.cq.tools.actool.comparators.TimestampPropertyComparator; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; public class HistoryUtils { private static final Logger LOG = LoggerFactory.getLogger(HistoryUtils.class); @@ -70,7 +70,7 @@ public static Node getAcHistoryRootNode(final Session session) * @return the node being created */ public static Node persistHistory(final Session session, - AcInstallationLog installLog, final int nrOfHistoriesToSave) + PersistableInstallationLogger installLog, final int nrOfHistoriesToSave) throws RepositoryException { Node acHistoryRootNode = getAcHistoryRootNode(session); @@ -108,7 +108,7 @@ private static Node safeGetNode(final Node baseNode, final String name, } public static void setHistoryNodeProperties(final Node historyNode, - AcInstallationLog installLog) throws ValueFormatException, + PersistableInstallationLogger installLog) throws ValueFormatException, VersionException, LockException, ConstraintViolationException, RepositoryException { diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceImpl.java index c2b08371..3254cdb2 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceImpl.java @@ -8,7 +8,7 @@ */ package biz.netcentric.cq.tools.actool.impl; -import static biz.netcentric.cq.tools.actool.history.AcInstallationLog.msHumanReadable; +import static biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger.msHumanReadable; import java.util.Arrays; import java.util.Collection; @@ -65,7 +65,8 @@ import biz.netcentric.cq.tools.actool.helper.PurgeHelper; import biz.netcentric.cq.tools.actool.helper.QueryHelper; import biz.netcentric.cq.tools.actool.history.AcHistoryService; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; import biz.netcentric.cq.tools.actool.installationhistory.AcInstallationHistoryPojo; @Service @@ -152,7 +153,7 @@ public InstallationLog apply(String[] restrictedToPaths) { @Override public InstallationLog apply(String configurationRootPath, String[] restrictedToPaths) { - AcInstallationLog installLog = new AcInstallationLog(); + PersistableInstallationLogger installLog = new PersistableInstallationLogger(); Session session = null; try { @@ -179,9 +180,10 @@ public InstallationLog apply(String configurationRootPath, String[] restrictedTo return installLog; } - /** Common entry point for JMX and install hook. */ + /** Common entry point for JMX and install hook, + * TODO: should not be exported as using non-API class PersistableInstllationLogger */ @Override - public void installConfigurationFiles(AcInstallationLog installLog, Map configurationFileContentsByFilename, + public void installConfigurationFiles(PersistableInstallationLogger installLog, Map configurationFileContentsByFilename, String[] restrictedToPaths, Session session) throws Exception { @@ -200,7 +202,6 @@ public void installConfigurationFiles(AcInstallationLog installLog, Map> repositoryDumpAceMap, String[] restrictedToPaths, Session session) throws Exception { if (acConfiguration.getAceConfig() == null) { @@ -237,23 +240,23 @@ private void installAcConfiguration( throw new IllegalArgumentException(message); } - installAuthorizables(installLog, acConfiguration.getAuthorizablesConfig(), session); + installAuthorizables(installLog, acConfiguration, session); installAces(installLog, acConfiguration, repositoryDumpAceMap, restrictedToPaths, session); } - private void removeAcesForPathsNotInConfig(AcInstallationLog installLog, Session session, Set principalsInConfig, - Map> repositoryDumpAceMap, AcesConfig aceBeansFromConfig) + private void removeAcesForPathsNotInConfig(InstallationLogger installLog, Session session, Set principalsInConfig, + Map> repositoryDumpAceMap, AcConfiguration acConfiguration) throws UnsupportedRepositoryOperationException, RepositoryException { int countAcesCleaned = 0; int countPathsCleaned = 0; Set relevantPathsForCleanup = getRelevantPathsForAceCleanup(principalsInConfig, repositoryDumpAceMap, - aceBeansFromConfig); + acConfiguration.getAceConfig()); for (String relevantPath : relevantPathsForCleanup) { - - Set principalsToRemoveAcesForAtThisPath = installLog.getAcConfiguration().getAuthorizablesConfig() + // TODO: why is acconfiguration retrieved from log? + Set principalsToRemoveAcesForAtThisPath = acConfiguration.getAuthorizablesConfig() .removeUnmanagedPrincipalNamesAtPath(relevantPath, principalsInConfig); // delete ACE if principal *is* in config, but the path *is not* in config @@ -360,18 +363,16 @@ Set collectPrincipalsToBeMigrated(AuthorizablesConfig authorizablesBeans return principalsToBeMigrated; } - private void installAces(AcInstallationLog installLog, + private void installAces(InstallationLogger installLog, AcConfiguration acConfiguration, Map> repositoryDumpAceMap, String[] restrictedToPaths, Session session) throws Exception { - AcesConfig aceBeansFromConfig = acConfiguration.getAceConfig(); - // --- installation of ACEs from configuration --- Map> pathBasedAceMapFromConfig = AcHelper - .getPathBasedAceMap(aceBeansFromConfig, AcHelper.ACE_ORDER_ACTOOL_BEST_PRACTICE); + .getPathBasedAceMap(acConfiguration.getAceConfig(), AcHelper.ACE_ORDER_ACTOOL_BEST_PRACTICE); Set principalsToRemoveAcesFor = getPrincipalNamesToRemoveAcesFor(acConfiguration.getAuthorizablesConfig()); - removeAcesForPathsNotInConfig(installLog, session, principalsToRemoveAcesFor, repositoryDumpAceMap, aceBeansFromConfig); + removeAcesForPathsNotInConfig(installLog, session, principalsToRemoveAcesFor, repositoryDumpAceMap, acConfiguration); Map> filteredPathBasedAceMapFromConfig = filterForRestrictedPaths(pathBasedAceMapFromConfig, restrictedToPaths, installLog); @@ -384,7 +385,7 @@ private void installAces(AcInstallationLog installLog, + filteredPathBasedAceMapFromConfig.size() + " paths in content nodes using strategy " + aceBeanInstaller.getClass().getSimpleName() + "..."); - aceBeanInstaller.installPathBasedACEs(filteredPathBasedAceMapFromConfig, session, installLog, principalsToRemoveAcesFor, + aceBeanInstaller.installPathBasedACEs(filteredPathBasedAceMapFromConfig, acConfiguration, session, installLog, principalsToRemoveAcesFor, intermediateSaves); // if everything went fine (no exceptions), save the session @@ -399,7 +400,7 @@ private void installAces(AcInstallationLog installLog, } private Map> filterForRestrictedPaths(Map> pathBasedAceMapFromConfig, - String[] restrictedToPaths, AcInstallationLog installLog) { + String[] restrictedToPaths, InstallationLogger installLog) { if (restrictedToPaths == null || restrictedToPaths.length == 0) { return pathBasedAceMapFromConfig; } @@ -428,19 +429,19 @@ private int collectAceCount(Map> aceMapFromConfig) { return count; } - private void installAuthorizables(AcInstallationLog installLog, AuthorizablesConfig authorizablesMapfromConfig, Session session) + private void installAuthorizables(InstallationLogger installLog, AcConfiguration acConfiguration, Session session) throws RepositoryException, Exception { // --- installation of Authorizables from configuration --- StopWatch stopWatch = new StopWatch(); stopWatch.start(); - - installLog.addMessage(LOG, "*** Starting installation of " + authorizablesMapfromConfig.size() + " authorizables..."); + AuthorizablesConfig authorizablesConfig = acConfiguration.getAuthorizablesConfig(); + installLog.addMessage(LOG, "*** Starting installation of " + authorizablesConfig.size() + " authorizables..."); try { // only save session if no exceptions occurred - authorizableCreatorService.installAuthorizables(authorizablesMapfromConfig, session, installLog); + authorizableCreatorService.installAuthorizables(acConfiguration, authorizablesConfig, session, installLog); if (intermediateSaves) { if (session.hasPendingChanges()) { @@ -460,7 +461,7 @@ private void installAuthorizables(AcInstallationLog installLog, AuthorizablesCon + msHumanReadable(stopWatch.getTime())); } - private void removeObsoleteAuthorizables(AcInstallationLog installLog, Set obsoleteAuthorizables, Session session) { + private void removeObsoleteAuthorizables(InstallationLogger installLog, Set obsoleteAuthorizables, Session session) { try { @@ -504,7 +505,7 @@ private void removeObsoleteAuthorizables(AcInstallationLog installLog, Set authorizabesFromConfigurations = getAllAuthorizablesFromConfig(session); message = purgeAuthorizables(authorizabesFromConfigurations, session); - AcInstallationLog installLog = new AcInstallationLog(); + PersistableInstallationLogger installLog = new PersistableInstallationLogger(); installLog.addMessage(LOG, "purge method: purgAuthorizablesFromConfig()"); installLog.addMessage(LOG, message); acHistoryService.persistAcePurgeHistory(installLog); @@ -633,7 +634,7 @@ public String purgeAuthorizables(String[] authorizableIds) { session = repository.loginService(Constants.USER_AC_SERVICE, null); Set authorizablesSet = new HashSet(Arrays.asList(authorizableIds)); message = purgeAuthorizables(authorizablesSet, session); - AcInstallationLog installLog = new AcInstallationLog(); + PersistableInstallationLogger installLog = new PersistableInstallationLogger(); installLog.addMessage(LOG, "purge method: purgeAuthorizables()"); installLog.addMessage(LOG, message); acHistoryService.persistAcePurgeHistory(installLog); @@ -673,7 +674,7 @@ private String purgeAuthorizables(Set authorizableIds, final Session ses session.save(); sw.stop(); - String executionTime = AcInstallationLog.msHumanReadable(sw.getTime()); + String executionTime = PersistableInstallationLogger.msHumanReadable(sw.getTime()); message.append("Purged " + authorizableIds.size() + " authorizables in " + executionTime + "\n"); } catch (Exception e) { @@ -727,7 +728,7 @@ public Set getCurrentConfigurationPaths() { public Set getAllAuthorizablesFromConfig(Session session) throws Exception { - AcInstallationLog history = new AcInstallationLog(); + PersistableInstallationLogger history = new PersistableInstallationLogger(); Map newestConfigurations = configFilesRetriever.getConfigFileContentFromNode(configuredAcConfigurationRootPath, session); AcConfiguration acConfiguration = configurationMerger.getMergedConfigurations(newestConfigurations, history, configReader, session); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceInternal.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceInternal.java index adeb8c32..b954a4ff 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceInternal.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/impl/AcInstallationServiceInternal.java @@ -14,7 +14,7 @@ import javax.jcr.Session; import biz.netcentric.cq.tools.actool.api.AcInstallationService; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; public interface AcInstallationServiceInternal extends AcInstallationService { @@ -25,7 +25,7 @@ public interface AcInstallationServiceInternal extends AcInstallationService { * @param restrictedToPaths only apply ACLs to root paths as given * @param a jcr session * @throws Exception */ - public void installConfigurationFiles(AcInstallationLog history, + public void installConfigurationFiles(PersistableInstallationLogger history, Map configurationFileContentsByFilename, String[] restrictedToPaths, Session session) throws Exception; diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java index afccf6a0..0f0c27ac 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/AcToolInstallHook.java @@ -14,7 +14,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; import biz.netcentric.cq.tools.actool.history.HistoryEntry; import biz.netcentric.cq.tools.actool.installhook.impl.AcToolInstallHookService; import biz.netcentric.cq.tools.actool.installhook.impl.OsgiAwareInstallHook; @@ -57,10 +57,10 @@ public void execute(InstallContext context) throws PackageException { } // try { - AcInstallationLog history; + PersistableInstallationLogger history; try { history = acService.installYamlFilesFromPackage(context - .getPackage().getArchive(), context.getSession()); + .getPackage().getArchive(), context.getSession(), context.getOptions().getListener()); } catch (Exception e) { log("Exception while installing configurations: " + e, @@ -69,17 +69,10 @@ public void execute(InstallContext context) throws PackageException { } if (!history.isSuccess()) { - for (HistoryEntry entry : history.getErrors()) { - log(entry.toString(), context.getOptions()); - } - throw new PackageException( - "Could not install configurations. Check log for detailed error message!"); + throw new PackageException("AC Tool installation failed with " + +history.getErrors().size()+ " errors. Check log for detailed error message(s)!"); } else { - // convert to correct (HTML) linebreaks for the package manager - String log = history.toString().replaceAll("\\\n", "
"); - log(log, context.getOptions()); - log("Installed ACLs successfully through AcToolInstallHook!", - context.getOptions()); + log("Installed ACLs successfully through AcToolInstallHook!", context.getOptions()); } } finally { getBundleContext().ungetService(acToolInstallHookService); diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookService.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookService.java index 9cbdef2e..e51f95fd 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookService.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookService.java @@ -10,13 +10,14 @@ import javax.jcr.Session; +import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener; import org.apache.jackrabbit.vault.fs.io.Archive; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; public interface AcToolInstallHookService { - public AcInstallationLog installYamlFilesFromPackage(Archive archive, Session session) + public PersistableInstallationLogger installYamlFilesFromPackage(Archive archive, Session session, ProgressTrackerListener progressTrackerListener) throws Exception; } \ No newline at end of file diff --git a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookServiceImpl.java b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookServiceImpl.java index d8f62210..bdc44825 100644 --- a/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookServiceImpl.java +++ b/accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/installhook/impl/AcToolInstallHookServiceImpl.java @@ -16,20 +16,18 @@ import org.apache.felix.scr.annotations.Component; import org.apache.felix.scr.annotations.Reference; import org.apache.felix.scr.annotations.Service; +import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener; import org.apache.jackrabbit.vault.fs.io.Archive; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; import biz.netcentric.cq.tools.actool.configreader.ConfigFilesRetriever; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; +import biz.netcentric.cq.tools.actool.history.ProgressTrackerListenerInstallationLogger; import biz.netcentric.cq.tools.actool.impl.AcInstallationServiceInternal; @Component @Service(value = AcToolInstallHookService.class) public class AcToolInstallHookServiceImpl implements AcToolInstallHookService { - private static final Logger LOG = LoggerFactory.getLogger(AcToolInstallHookServiceImpl.class); - @Reference private AcInstallationServiceInternal acInstallationService; @@ -37,10 +35,9 @@ public class AcToolInstallHookServiceImpl implements AcToolInstallHookService { private ConfigFilesRetriever configFilesRetriever; @Override - public AcInstallationLog installYamlFilesFromPackage(Archive archive, Session session) + public PersistableInstallationLogger installYamlFilesFromPackage(Archive archive, Session session, ProgressTrackerListener progressTrackerListener) throws Exception { - AcInstallationLog history = new AcInstallationLog(); - + PersistableInstallationLogger history = new ProgressTrackerListenerInstallationLogger(progressTrackerListener); Map configs = configFilesRetriever.getConfigFileContentFromPackage(archive); history.setCrxPackageName(getArchiveName(archive)); String[] restrictedToPaths = null; // never use path restriction for hook usage for now diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncrementalTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncrementalTest.java index 347401b2..e90ad54c 100644 --- a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncrementalTest.java +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/aceinstaller/AceBeanInstallerIncrementalTest.java @@ -58,7 +58,8 @@ import biz.netcentric.cq.tools.actool.configmodel.AceBean; import biz.netcentric.cq.tools.actool.configmodel.Restriction; import biz.netcentric.cq.tools.actool.configreader.YamlConfigReader; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; public class AceBeanInstallerIncrementalTest { @@ -84,7 +85,7 @@ public class AceBeanInstallerIncrementalTest { AceBeanInstallerIncremental aceBeanInstallerIncremental; @Spy - AcInstallationLog installLog; + PersistableInstallationLogger installLog; @Mock JackrabbitAccessControlList jackrabbitAccessControlList; diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImplTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImplTest.java index 1b7bb5da..b4d371f4 100644 --- a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImplTest.java +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/authorizableinstaller/impl/AuthorizableInstallerServiceImplTest.java @@ -22,6 +22,7 @@ import static org.mockito.Mockito.verifyZeroInteractions; import java.util.Arrays; +import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -40,248 +41,308 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.junit.runners.Enclosed; +import org.junit.runners.Parameterized; import org.mockito.Matchers; import org.mockito.Mock; import org.mockito.Mockito; +import org.mockito.MockitoAnnotations; import org.mockito.Spy; import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; +import com.adobe.granite.crypto.CryptoException; +import com.adobe.granite.crypto.CryptoSupport; + import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean; import biz.netcentric.cq.tools.actool.configmodel.GlobalConfiguration; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; -@RunWith(MockitoJUnitRunner.class) +@RunWith(Enclosed.class) public class AuthorizableInstallerServiceImplTest { - public static final String TESTGROUP = "testGroup"; + @RunWith(MockitoJUnitRunner.class) + public static final class BASE_TESTS { + public static final String TESTGROUP = "testGroup"; - public static final String GROUP1 = "group1"; - public static final String GROUP2 = "group2"; - public static final String GROUP3 = "group3"; - public static final String EXTERNALGROUP = "externalGroup"; + public static final String GROUP1 = "group1"; + public static final String GROUP2 = "group2"; + public static final String GROUP3 = "group3"; + public static final String EXTERNALGROUP = "externalGroup"; - public static final String USER1 = "user1"; + public static final String USER1 = "user1"; - public static final String SYSTEM_USER1 = "systemuser1"; + public static final String SYSTEM_USER1 = "systemuser1"; - // class under test - @Spy - private AuthorizableInstallerServiceImpl cut = new AuthorizableInstallerServiceImpl(); - - private AcConfiguration acConfiguration = new AcConfiguration(); - private GlobalConfiguration globalConfiguration = new GlobalConfiguration(); - private AcInstallationLog status = new AcInstallationLog(); + // class under test + @Spy + private AuthorizableInstallerServiceImpl cut = new AuthorizableInstallerServiceImpl(); - @Mock - private UserManager userManager; + private AcConfiguration acConfiguration = new AcConfiguration(); + private GlobalConfiguration globalConfiguration = new GlobalConfiguration(); + private PersistableInstallationLogger status = new PersistableInstallationLogger(); - @Mock - private Session session; - @Mock - private ValueFactory valueFactory; + @Mock + private UserManager userManager; - @Mock - private Group testGroup; + @Mock + private Session session; + @Mock + private ValueFactory valueFactory; - @Mock - private Group group1; + @Mock + private Group testGroup; - @Mock - private Group group2; + @Mock + private Group group1; - @Mock - private Group group3; + @Mock + private Group group2; - @Mock - private Group externalGroup; - - @Mock - private User systemUser1; + @Mock + private Group group3; - @Mock - private User regularUser1; + @Mock + private Group externalGroup; - @Before - public void setup() throws RepositoryException { + @Mock + private User systemUser1; - doReturn(valueFactory).when(session).getValueFactory(); - Mockito.when(valueFactory.createValue(anyString())).thenAnswer(new Answer() { - @Override - public Value answer(InvocationOnMock invocation) throws Throwable { - Value mock = mock(Value.class); - Object val = invocation.getArguments()[0]; - doReturn(val).when(mock).getString(); - return mock; - } - }); + @Mock + private User regularUser1; - status.setAcConfiguration(acConfiguration); - acConfiguration.setGlobalConfiguration(globalConfiguration); + @Before + public void setup() throws RepositoryException { - setupAuthorizable(testGroup, TESTGROUP, true, false); - setupAuthorizable(group1, GROUP1, true, false); - setupAuthorizable(group2, GROUP2, true, false); - setupAuthorizable(group3, GROUP3, true, false); - setupAuthorizable(externalGroup, EXTERNALGROUP, true, false); + doReturn(valueFactory).when(session).getValueFactory(); + Mockito.when(valueFactory.createValue(anyString())).thenAnswer(new Answer() { + @Override + public Value answer(InvocationOnMock invocation) throws Throwable { + Value mock = mock(Value.class); + Object val = invocation.getArguments()[0]; + doReturn(val).when(mock).getString(); + return mock; + } + }); - setupAuthorizable(systemUser1, SYSTEM_USER1, false, true); - setupAuthorizable(regularUser1, USER1, false, false); - } + acConfiguration.setGlobalConfiguration(globalConfiguration); - private void setupAuthorizable(Authorizable authorizable, String id, boolean isGroup, boolean isSystemUser) throws RepositoryException { - doReturn(authorizable).when(userManager).getAuthorizable(id); - doReturn(id).when(authorizable).getID(); - doReturn(isGroup).when(authorizable).isGroup(); - doReturn("/home/" + (isGroup ? "groups" : "users") + (isSystemUser ? "/system" : "") + "/test").when(authorizable).getPath(); - } - - @Test - public void testApplyGroupMembershipConfigIsMemberOf() throws Exception { - HashSet configuredGroups = new HashSet(Arrays.asList(GROUP1, GROUP2)); - HashSet groupsInRepo = new HashSet(Arrays.asList(GROUP2, GROUP3, EXTERNALGROUP)); - - globalConfiguration.setDefaultUnmanagedExternalIsMemberOfRegex("external.*"); - - // just return the value as passed in as fourth argument - doAnswer(new Answer>() { - public Set answer(InvocationOnMock invocation) throws Throwable { - return (Set) invocation.getArguments()[3]; - } - }).when(cut).validateAssignedGroups(userManager, null, TESTGROUP, configuredGroups, status); - - Set authorizablesInConfig = new HashSet(asList(GROUP1)); - cut.applyGroupMembershipConfigIsMemberOf(TESTGROUP, status, userManager, null, configuredGroups, groupsInRepo, - authorizablesInConfig); - - verifyZeroInteractions(group2); // in configuredGroups and in groupsInRepo - verifyZeroInteractions(externalGroup); // matches external.* and hence must not be removed (even though it is not in the - // configuration) - - verify(group1).addMember(testGroup); - verifyNoMoreInteractions(group1); - - verify(group3).removeMember(testGroup); - verifyNoMoreInteractions(group3); - - } - - @Test - public void testApplyGroupMembershipConfigMembers() throws Exception { - - AcInstallationLog history = new AcInstallationLog(); - history.setAcConfiguration(new AcConfiguration()); - history.getAcConfiguration().setGlobalConfiguration(new GlobalConfiguration()); - - AuthorizableConfigBean authorizableConfigBean = new AuthorizableConfigBean(); - authorizableConfigBean.setAuthorizableId(TESTGROUP); - - Set authorizablesInConfig = new HashSet(asList(GROUP1)); - - // test no change - authorizableConfigBean.setMembers(new String[] { GROUP2, GROUP3, SYSTEM_USER1 }); - doReturn(asList(group2, group3, regularUser1, systemUser1).iterator()).when(testGroup).getDeclaredMembers(); - cut.applyGroupMembershipConfigMembers(authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); - verify(testGroup, times(0)).addMember(any(Authorizable.class)); - verify(testGroup, times(0)).removeMember(any(Authorizable.class)); - reset(testGroup); - - // test removed in config - authorizableConfigBean.setMembers(new String[] {}); - doReturn(asList(group2, group3, regularUser1, systemUser1).iterator()).when(testGroup).getDeclaredMembers(); - cut.applyGroupMembershipConfigMembers(authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); - verify(testGroup, times(0)).addMember(any(Authorizable.class)); - verify(testGroup).removeMember(group2); - verify(testGroup).removeMember(group3); - verify(testGroup).removeMember(systemUser1); - verify(testGroup, times(0)).removeMember(regularUser1);// regular user must not be removed - reset(testGroup); - - // test to be added as in config but not in repo - authorizableConfigBean.setMembers(new String[] { GROUP2, GROUP3, SYSTEM_USER1 }); - doReturn(asList().iterator()).when(testGroup).getDeclaredMembers(); - cut.applyGroupMembershipConfigMembers(authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); - verify(testGroup).addMember(group2); - verify(testGroup).addMember(group3); - verify(testGroup).addMember(systemUser1); - verify(testGroup, times(0)).removeMember(any(Authorizable.class)); - reset(testGroup); - - // test authorizable in config not removed - authorizableConfigBean.setMembers(new String[] {}); - doReturn(asList(group1, group2).iterator()).when(testGroup).getDeclaredMembers(); - cut.applyGroupMembershipConfigMembers(authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); - verify(testGroup, times(0)).addMember(any(Authorizable.class)); - verify(testGroup, times(0)).removeMember(group1); // must not be removed since it's contained in config - verify(testGroup).removeMember(group2); - reset(testGroup); - - // test authorizable in config not removed if defaultUnmanagedExternalMembersRegex is configured - history.getAcConfiguration().getGlobalConfiguration().setDefaultUnmanagedExternalMembersRegex("group2.*"); - authorizableConfigBean.setMembers(new String[] {}); - doReturn(asList(group1, group2).iterator()).when(testGroup).getDeclaredMembers(); - cut.applyGroupMembershipConfigMembers(authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); - verify(testGroup, times(0)).addMember(any(Authorizable.class)); - verify(testGroup, times(0)).removeMember(group1); // must not be removed since it's contained in config - verify(testGroup, times(0)).removeMember(group2); // must not be removed since allowExternalGroupNamesRegEx config - reset(testGroup); + setupAuthorizable(testGroup, TESTGROUP, true, false); + setupAuthorizable(group1, GROUP1, true, false); + setupAuthorizable(group2, GROUP2, true, false); + setupAuthorizable(group3, GROUP3, true, false); + setupAuthorizable(externalGroup, EXTERNALGROUP, true, false); - } - - - @Test - public void testSetAuthorizableProperties() throws Exception { - - AuthorizableConfigBean authorizableConfig = new AuthorizableConfigBean(); - authorizableConfig.setIsGroup(false); + setupAuthorizable(systemUser1, SYSTEM_USER1, false, true); + setupAuthorizable(regularUser1, USER1, false, false); + } - authorizableConfig.setName("John Doe"); - authorizableConfig.setDescription("Test Description"); + private void setupAuthorizable(Authorizable authorizable, String id, boolean isGroup, boolean isSystemUser) throws RepositoryException { + doReturn(authorizable).when(userManager).getAuthorizable(id); + doReturn(id).when(authorizable).getID(); + doReturn(isGroup).when(authorizable).isGroup(); + doReturn("/home/" + (isGroup ? "groups" : "users") + (isSystemUser ? "/system" : "") + "/test").when(authorizable).getPath(); + } - cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); + @Test + public void testApplyGroupMembershipConfigIsMemberOf() throws Exception { + HashSet configuredGroups = new HashSet(Arrays.asList(GROUP1, GROUP2)); + HashSet groupsInRepo = new HashSet(Arrays.asList(GROUP2, GROUP3, EXTERNALGROUP)); - verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("John"))); - verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Doe"))); - verify(regularUser1).setProperty(eq("profile/aboutMe"), Matchers.argThat(new ValueMatcher("Test Description"))); + globalConfiguration.setDefaultUnmanagedExternalIsMemberOfRegex("external.*"); - authorizableConfig.setName("Van der Broek, Sebastian"); - cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); - verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("Sebastian"))); - verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Van der Broek"))); + // just return the value as passed in as fourth argument + doAnswer(new Answer>() { + public Set answer(InvocationOnMock invocation) throws Throwable { + return (Set) invocation.getArguments()[4]; + } + }).when(cut).validateAssignedGroups(userManager, acConfiguration.getAuthorizablesConfig(), null, TESTGROUP, configuredGroups, status); - authorizableConfig.setName("Johann Sebastian Bach"); - cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); - verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("Johann Sebastian"))); - verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Bach"))); + Set authorizablesInConfig = new HashSet(asList(GROUP1)); + cut.applyGroupMembershipConfigIsMemberOf(TESTGROUP, acConfiguration, status, userManager, null, configuredGroups, groupsInRepo, + authorizablesInConfig); - } + verifyZeroInteractions(group2); // in configuredGroups and in groupsInRepo + verifyZeroInteractions(externalGroup); // matches external.* and hence must not be removed (even though it is not in the + // configuration) - private final class ValueMatcher extends BaseMatcher { - private String expectedVal; + verify(group1).addMember(testGroup); + verifyNoMoreInteractions(group1); + + verify(group3).removeMember(testGroup); + verifyNoMoreInteractions(group3); + + } + + @Test + public void testApplyGroupMembershipConfigMembers() throws Exception { + + PersistableInstallationLogger history = new PersistableInstallationLogger(); + acConfiguration.setGlobalConfiguration(new GlobalConfiguration()); + + AuthorizableConfigBean authorizableConfigBean = new AuthorizableConfigBean(); + authorizableConfigBean.setAuthorizableId(TESTGROUP); + + Set authorizablesInConfig = new HashSet(asList(GROUP1)); + + // test no change + authorizableConfigBean.setMembers(new String[] { GROUP2, GROUP3, SYSTEM_USER1 }); + doReturn(asList(group2, group3, regularUser1, systemUser1).iterator()).when(testGroup).getDeclaredMembers(); + cut.applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); + verify(testGroup, times(0)).addMember(any(Authorizable.class)); + verify(testGroup, times(0)).removeMember(any(Authorizable.class)); + reset(testGroup); + + // test removed in config + authorizableConfigBean.setMembers(new String[] {}); + doReturn(asList(group2, group3, regularUser1, systemUser1).iterator()).when(testGroup).getDeclaredMembers(); + cut.applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); + verify(testGroup, times(0)).addMember(any(Authorizable.class)); + verify(testGroup).removeMember(group2); + verify(testGroup).removeMember(group3); + verify(testGroup).removeMember(systemUser1); + verify(testGroup, times(0)).removeMember(regularUser1);// regular user must not be removed + reset(testGroup); + + // test to be added as in config but not in repo + authorizableConfigBean.setMembers(new String[] { GROUP2, GROUP3, SYSTEM_USER1 }); + doReturn(asList().iterator()).when(testGroup).getDeclaredMembers(); + cut.applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); + verify(testGroup).addMember(group2); + verify(testGroup).addMember(group3); + verify(testGroup).addMember(systemUser1); + verify(testGroup, times(0)).removeMember(any(Authorizable.class)); + reset(testGroup); + + // test authorizable in config not removed + authorizableConfigBean.setMembers(new String[] {}); + doReturn(asList(group1, group2).iterator()).when(testGroup).getDeclaredMembers(); + cut.applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); + verify(testGroup, times(0)).addMember(any(Authorizable.class)); + verify(testGroup, times(0)).removeMember(group1); // must not be removed since it's contained in config + verify(testGroup).removeMember(group2); + reset(testGroup); + + // test authorizable in config not removed if defaultUnmanagedExternalMembersRegex is configured + acConfiguration.getGlobalConfiguration().setDefaultUnmanagedExternalMembersRegex("group2.*"); + authorizableConfigBean.setMembers(new String[] {}); + doReturn(asList(group1, group2).iterator()).when(testGroup).getDeclaredMembers(); + cut.applyGroupMembershipConfigMembers(acConfiguration, authorizableConfigBean, history, TESTGROUP, userManager, authorizablesInConfig); + verify(testGroup, times(0)).addMember(any(Authorizable.class)); + verify(testGroup, times(0)).removeMember(group1); // must not be removed since it's contained in config + verify(testGroup, times(0)).removeMember(group2); // must not be removed since allowExternalGroupNamesRegEx config + reset(testGroup); - public ValueMatcher(String expectedVal) { - this.expectedVal = expectedVal; } - @Override - public boolean matches(Object actualVal) { - if (!(actualVal instanceof Value)) { - return false; - } else { - try { - return StringUtils.equals(((Value) actualVal).getString(), expectedVal); - } catch (IllegalStateException | RepositoryException e) { + + @Test + public void testSetAuthorizableProperties() throws Exception { + + AuthorizableConfigBean authorizableConfig = new AuthorizableConfigBean(); + authorizableConfig.setIsGroup(false); + + authorizableConfig.setName("John Doe"); + authorizableConfig.setDescription("Test Description"); + + cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); + + verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("John"))); + verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Doe"))); + verify(regularUser1).setProperty(eq("profile/aboutMe"), Matchers.argThat(new ValueMatcher("Test Description"))); + + authorizableConfig.setName("Van der Broek, Sebastian"); + cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); + verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("Sebastian"))); + verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Van der Broek"))); + + authorizableConfig.setName("Johann Sebastian Bach"); + cut.setAuthorizableProperties(regularUser1, authorizableConfig, session, status); + verify(regularUser1).setProperty(eq("profile/givenName"), Matchers.argThat(new ValueMatcher("Johann Sebastian"))); + verify(regularUser1).setProperty(eq("profile/familyName"), Matchers.argThat(new ValueMatcher("Bach"))); + + } + + private final class ValueMatcher extends BaseMatcher { + private String expectedVal; + + public ValueMatcher(String expectedVal) { + this.expectedVal = expectedVal; + } + + @Override + public boolean matches(Object actualVal) { + if (!(actualVal instanceof Value)) { return false; + } else { + try { + return StringUtils.equals(((Value) actualVal).getString(), expectedVal); + } catch (IllegalStateException | RepositoryException e) { + return false; + } } + } + @Override + public void describeTo(Description desc) { + desc.appendText(" is " + expectedVal); + } } + } + + @RunWith(Parameterized.class) + public static final class SetUserPassword { + + private static final String UNPROTECTED_PASSWORD = "unprotected_pass"; + + @Mock + private User user; + + @Mock + private CryptoSupport cryptoSupportMock; + + private AuthorizableInstallerServiceImpl service; + + private String password; + private String expectedPassword; + + public SetUserPassword(String password, String expectedPassword) { + this.password = password; + this.expectedPassword = expectedPassword; + } + + @Parameterized.Parameters + public static Collection data() { + return Arrays.asList(new Object[][] { + { "{some_protected_pass}", UNPROTECTED_PASSWORD }, + { "bracketsAtTheEnd{pass}", "bracketsAtTheEnd{pass}" }, + { "{pass}bracketsAtTheStart", "{pass}bracketsAtTheStart" }, + { "bracketsIn{pass}TheMiddle", "bracketsIn{pass}TheMiddle" }, + { "noBrackets", "noBrackets" }, + }); + } + + @Before + public void setUp() throws CryptoException { + MockitoAnnotations.initMocks(this); + + service = new AuthorizableInstallerServiceImpl(); + service.cryptoSupport = cryptoSupportMock; + + doReturn(UNPROTECTED_PASSWORD).when(cryptoSupportMock).unprotect(anyString()); + } + + @Test + public void test() throws RepositoryException, CryptoException { + final AuthorizableConfigBean bean = new AuthorizableConfigBean(); + bean.setPassword(password); + + service.setUserPassword(bean, user); - @Override - public void describeTo(Description desc) { - desc.appendText(" is " + expectedVal); + verify(user).changePassword(eq(expectedPassword)); } } } diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMergerTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMergerTest.java index 22ebae0f..b6e768b2 100644 --- a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMergerTest.java +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigurationMergerTest.java @@ -28,7 +28,7 @@ import biz.netcentric.cq.tools.actool.configmodel.AcConfiguration; import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean; import biz.netcentric.cq.tools.actool.configmodel.AuthorizablesConfig; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.PersistableInstallationLogger; import biz.netcentric.cq.tools.actool.validators.exceptions.AcConfigBeanValidationException; import biz.netcentric.cq.tools.actool.validators.impl.ObsoleteAuthorizablesValidatorImpl; @@ -56,7 +56,7 @@ public void testMemberGroups() throws IOException, RepositoryException, AcConfig final ConfigReader reader = new YamlConfigReader(); final Map configs = new HashMap(); configs.put("/etc/config", config); - AcConfiguration acConfiguration = merger.getMergedConfigurations(configs, mock(AcInstallationLog.class), reader, session); + AcConfiguration acConfiguration = merger.getMergedConfigurations(configs, mock(PersistableInstallationLogger.class), reader, session); final AuthorizablesConfig groups = acConfiguration.getAuthorizablesConfig(); final AuthorizableConfigBean groupA = groups.getAuthorizableConfig("groupA"); assertEquals(3, groupA.getMemberOf().length); @@ -75,7 +75,7 @@ public void testEnsureIsMemberOfIsUsedWherePossible() throws RepositoryException final Map configs = new HashMap(); configs.put("/etc/config", config); - AcConfiguration acConfiguration = merger.getMergedConfigurations(configs, mock(AcInstallationLog.class), reader, session); + AcConfiguration acConfiguration = merger.getMergedConfigurations(configs, mock(PersistableInstallationLogger.class), reader, session); AuthorizableConfigBean groupAConfig = acConfiguration.getAuthorizablesConfig().getAuthorizableConfig("groupA"); assertEquals("groupA", groupAConfig.getAuthorizableId()); diff --git a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorTest.java b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorTest.java index e94127d5..29d67061 100644 --- a/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorTest.java +++ b/accesscontroltool-bundle/src/test/java/biz/netcentric/cq/tools/actool/configreader/YamlMacroProcessorTest.java @@ -37,7 +37,7 @@ import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean; import biz.netcentric.cq.tools.actool.configmodel.AuthorizablesConfig; import biz.netcentric.cq.tools.actool.configmodel.GlobalConfiguration; -import biz.netcentric.cq.tools.actool.history.AcInstallationLog; +import biz.netcentric.cq.tools.actool.history.InstallationLogger; import biz.netcentric.cq.tools.actool.validators.exceptions.AcConfigBeanValidationException; public class YamlMacroProcessorTest { @@ -46,7 +46,7 @@ public class YamlMacroProcessorTest { YamlMacroChildNodeObjectsProviderImpl yamlMacroChildNodeObjectsProvider; @Mock - AcInstallationLog installLog; + InstallationLogger installLog; @Mock Session session; diff --git a/accesscontroltool-exampleconfig-package/pom.xml b/accesscontroltool-exampleconfig-package/pom.xml index ee5149c1..cb506b93 100644 --- a/accesscontroltool-exampleconfig-package/pom.xml +++ b/accesscontroltool-exampleconfig-package/pom.xml @@ -15,7 +15,7 @@ biz.netcentric.cq.tools.accesscontroltool accesscontroltool - 2.0.3 + 2.0.4 diff --git a/accesscontroltool-oakindex-package/pom.xml b/accesscontroltool-oakindex-package/pom.xml index c9ad4d55..27d814ba 100644 --- a/accesscontroltool-oakindex-package/pom.xml +++ b/accesscontroltool-oakindex-package/pom.xml @@ -15,7 +15,7 @@ biz.netcentric.cq.tools.accesscontroltool accesscontroltool - 2.0.3 + 2.0.4 diff --git a/accesscontroltool-package/pom.xml b/accesscontroltool-package/pom.xml index 10e191fe..f57f6d3a 100644 --- a/accesscontroltool-package/pom.xml +++ b/accesscontroltool-package/pom.xml @@ -15,7 +15,7 @@ biz.netcentric.cq.tools.accesscontroltool accesscontroltool - 2.0.3 + 2.0.4 diff --git a/docs/AdvancedFeatures.md b/docs/AdvancedFeatures.md index 0053337a..8b8173bb 100644 --- a/docs/AdvancedFeatures.md +++ b/docs/AdvancedFeatures.md @@ -167,7 +167,7 @@ Variables can also be declared to be an array and used in a loop: ## Configure permissions for anonymous -To configure permissions for out-of-the-box anonymous user, it's best to create a custom group and add user `anonymous` to the `members` attribute of that group. The ACEs added to the custom group will then be effective for anonyomous users. +To configure permissions for out-of-the-box anonymous user, it's best to create a custom group and add user `anonymous` to the `members` attribute of that group. The ACEs added to the custom group will then be effective for anonyomous user. ## Configure memberships of/towards externally managed groups diff --git a/docs/Configuration.md b/docs/Configuration.md index c876a352..5d97c0da 100644 --- a/docs/Configuration.md +++ b/docs/Configuration.md @@ -77,7 +77,7 @@ property | comment | required --- | --- | --- name | Works mostly like for groups, except that the string is split up in first and last name using the last space found in string. For instance "Johann Sebastian Bach" will result in first name "Johann Sebastian" and last name "Bach". For names where the split has to be explicitly configured, use a comma: "Van der Broek, Sebastian" will result in first name "Sebastian" and last name "Van der Broek" | optional description, path, isMemberOf | Work exactly as for groups | optional -password | The PW for the user. Obviously this is stored in plain text and should only be used for test users | Required for non-system users, otherwise must not be set +password | The PW for the user. Can be stored in plain text (only to be used for test users). If a password value is enclosed in brackets, then it will be automatically decrypted using com.adobe.granite.crypto.CryptoSupport. `/system/console/crypto` on target instance can be used to get encrypted password. Encrypted password (together with braces) should also be enclosed in double quotes. | Required for non-system users, otherwise must not be set isSystemUser | Create users as system user (AEM 6.1 and later) | optional disabled | Can be set to `true` or an arbitrary reason string to disable a user. If set to `false` the user will be explicitly enabled (calling `User.disable(null)`). If omitted will not change anything regarding enabled/disabled status of user | optional profileContent | Allows to provide [enhanced docview xml](https://jackrabbit.apache.org/filevault/apidocs/org/apache/jackrabbit/vault/util/DocViewProperty.html) that will reset the profile to the given structure after each run (since v1.8.2, enhanced docview since v1.9.1) | optional @@ -92,6 +92,10 @@ Example: - isMemberOf: myeditors password: secret + - replicationReceiver: + - name: "Replication receiver" + password: "{someEncryptedValue}" + - poweruser: - name: "Power User" isMemberOf: powerusers diff --git a/pom.xml b/pom.xml index b1da04f2..20eec251 100644 --- a/pom.xml +++ b/pom.xml @@ -11,7 +11,7 @@ biz.netcentric.cq.tools.accesscontroltool accesscontroltool - 2.0.3 + 2.0.4 pom Access Control Tool - Reactor Project @@ -107,6 +107,12 @@ 5.6.4 provided + + com.adobe.granite + com.adobe.granite.crypto + 3.0.0 + provided + org.osgi org.osgi.core