Skip to content

Commit f90e206

Browse files
authored
Merge pull request #445 from Netcentric/bugfix/fix-duplicate-aces-in-dump
Rely on paths instead of Nodes in the set to remove duplicates
2 parents 9f96d6c + cb82dc0 commit f90e206

File tree

3 files changed

+60
-56
lines changed

3 files changed

+60
-56
lines changed

Diff for: accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/configreader/YamlConfigReader.java

+5-10
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
package biz.netcentric.cq.tools.actool.configreader;
1010

1111
import java.io.IOException;
12-
import java.security.GeneralSecurityException;
1312
import java.security.InvalidKeyException;
1413
import java.security.NoSuchAlgorithmException;
1514
import java.security.cert.CertificateException;
@@ -22,11 +21,9 @@
2221
import java.util.LinkedHashMap;
2322
import java.util.List;
2423
import java.util.Map;
25-
import java.util.Set;
2624
import java.util.Map.Entry;
27-
import java.util.regex.Pattern;
25+
import java.util.Set;
2826

29-
import javax.jcr.Node;
3027
import javax.jcr.RepositoryException;
3128
import javax.jcr.Session;
3229
import javax.jcr.query.InvalidQueryException;
@@ -39,8 +36,6 @@
3936
import org.slf4j.Logger;
4037
import org.slf4j.LoggerFactory;
4138

42-
import com.adobe.granite.crypto.CryptoSupport;
43-
4439
import biz.netcentric.cq.tools.actool.configmodel.AceBean;
4540
import biz.netcentric.cq.tools.actool.configmodel.AcesConfig;
4641
import biz.netcentric.cq.tools.actool.configmodel.AuthorizableConfigBean;
@@ -287,16 +282,16 @@ protected void handleWildcards(final Session session,
287282
RepositoryException {
288283
// perform query using the path containing wildcards
289284
final String query = "/jcr:root" + tmpAclBean.getJcrPath();
290-
final Set<Node> result = QueryHelper.getNodes(session, query);
285+
final Set<String> result = QueryHelper.getNodePathsFromQuery(session, query);
291286

292287
if (result.isEmpty()) {
293288
return;
294289
}
295-
for (final Node node : result) {
290+
for (final String path : result) {
296291
// ignore rep:policy nodes
297-
if (!node.getPath().contains("/rep:policy")) {
292+
if (!path.contains("/rep:policy")) {
298293
final AceBean replacementBean = tmpAclBean.clone();
299-
replacementBean.setJcrPath(node.getPath());
294+
replacementBean.setJcrPath(path);
300295

301296
if (aceSet.add(replacementBean)) {
302297
LOG.info("Wildcard replacement: Cloned " + tmpAclBean + " to " + replacementBean);

Diff for: accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/dumpservice/impl/DumpServiceImpl.java

+7-8
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
import javax.jcr.nodetype.NoSuchNodeTypeException;
3737
import javax.jcr.security.AccessControlEntry;
3838
import javax.jcr.version.VersionException;
39-
import javax.servlet.ServletOutputStream;
4039

4140
import org.apache.commons.lang3.StringUtils;
4241
import org.apache.jackrabbit.api.JackrabbitSession;
@@ -51,7 +50,7 @@
5150
import org.apache.jackrabbit.api.security.user.UserManager;
5251
import org.apache.jackrabbit.oak.spi.security.principal.EveryonePrincipal;
5352
import org.apache.jackrabbit.oak.spi.security.principal.PrincipalImpl;
54-
import org.apache.sling.api.SlingHttpServletResponse;
53+
import org.apache.jackrabbit.util.Text;
5554
import org.apache.sling.jcr.api.SlingRepository;
5655
import org.osgi.service.component.annotations.Activate;
5756
import org.osgi.service.component.annotations.Component;
@@ -348,19 +347,19 @@ public Set<AclBean> getACLDumpBeans(final Session session)
348347
throws RepositoryException {
349348

350349
List<String> excludeNodesList = Arrays.asList(queryExcludePaths);
351-
Set<Node> resultNodeSet = QueryHelper.getRepPolicyNodes(session, excludeNodesList);
350+
Set<String> resultPaths = QueryHelper.getRepPolicyNodePaths(session, excludeNodesList);
352351
Set<AclBean> accessControBeanSet = new LinkedHashSet<AclBean>();
353352

354353
// assemble big query result set using the query results of the child
355354
// paths of jcr:root node
356-
for (Node node : resultNodeSet) {
355+
for (String path : resultPaths) {
357356
try {
358-
String path = !Constants.REPO_POLICY_NODE.equals(node.getName())
359-
? node.getParent().getPath()
357+
String contextPath = !Constants.REPO_POLICY_NODE.equals(Text.getName(path))
358+
? Text.getRelativeParent(path, 1)
360359
: null /*  repo policies are accessed by using a null path */;
361360

362-
JackrabbitAccessControlList jackrabbitAcl = AccessControlUtils.getAccessControlList(session, path);
363-
AclBean aclBean = new AclBean(jackrabbitAcl, path);
361+
JackrabbitAccessControlList jackrabbitAcl = AccessControlUtils.getAccessControlList(session, contextPath);
362+
AclBean aclBean = new AclBean(jackrabbitAcl, contextPath);
364363
accessControBeanSet.add(aclBean);
365364
} catch (AccessDeniedException e) {
366365
LOG.error("AccessDeniedException: {}", e);

Diff for: accesscontroltool-bundle/src/main/java/biz/netcentric/cq/tools/actool/helper/QueryHelper.java

+48-38
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@
1010

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

13+
import java.util.Collection;
1314
import java.util.HashSet;
1415
import java.util.Iterator;
15-
import java.util.LinkedHashSet;
16+
import java.util.LinkedList;
1617
import java.util.List;
1718
import java.util.Set;
1819
import java.util.TreeSet;
@@ -34,6 +35,7 @@
3435
import org.apache.commons.lang3.StringUtils;
3536
import org.apache.commons.lang3.time.StopWatch;
3637
import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
38+
import org.apache.jackrabbit.util.Text;
3739
import org.slf4j.Logger;
3840
import org.slf4j.LoggerFactory;
3941

@@ -51,7 +53,7 @@ public class QueryHelper {
5153
* @param session the JCR session
5254
* @param excludePaths paths which are excluded from search
5355
* @return all rep:policy nodes delivered by query */
54-
public static Set<Node> getRepPolicyNodes(final Session session,
56+
public static Set<String> getRepPolicyNodePaths(final Session session,
5557
final List<String> excludePaths) {
5658
NodeIterator nodeIt = null;
5759
try {
@@ -60,7 +62,7 @@ public static Set<Node> getRepPolicyNodes(final Session session,
6062
LOG.error("Exception: {}", e);
6163
}
6264

63-
Set<String> paths = new TreeSet<String>();
65+
Set<String> rootChildrenPaths = new TreeSet<String>();
6466
while (nodeIt.hasNext()) {
6567
String currentPath = null;
6668
Node currentNode = nodeIt.nextNode();
@@ -73,26 +75,26 @@ public static Set<Node> getRepPolicyNodes(final Session session,
7375
try {
7476
if (!currentNode.hasProperty("rep:AuthorizableFolder")) {
7577
if (!excludePaths.contains(currentPath)) {
76-
paths.add(currentPath);
78+
rootChildrenPaths.add(currentPath);
7779
}
7880
}
7981
} catch (RepositoryException e) {
8082
LOG.error("Exception: {}", e);
8183
}
8284
}
83-
Set<Node> nodes = new LinkedHashSet<Node>();
85+
Set<String> paths = new HashSet<>();
8486
try {
8587
// get the rep:policy node of "/", if existing
8688
if (session.nodeExists(ROOT_REP_POLICY_NODE)) {
87-
nodes.add(session.getNode(ROOT_REP_POLICY_NODE));
89+
paths.add(ROOT_REP_POLICY_NODE);
8890
}
8991
if (session.nodeExists(ROOT_REPO_POLICY_NODE)) {
90-
nodes.add(session.getNode(ROOT_REPO_POLICY_NODE));
92+
paths.add(ROOT_REPO_POLICY_NODE);
9193
}
9294

9395
// get the rep:policy node of "/home", if existing
9496
if (session.nodeExists(HOME_REP_POLICY)) {
95-
nodes.add(session.getNode(HOME_REP_POLICY));
97+
paths.add(HOME_REP_POLICY);
9698
}
9799

98100
boolean indexForRepACLExists = session.nodeExists(OAK_INDEX_PATH_REP_ACL);
@@ -102,65 +104,69 @@ public static Set<Node> getRepPolicyNodes(final Session session,
102104
"SELECT ace.* FROM [rep:ACE] AS ace WHERE ace.[rep:principalName] IS NOT NULL AND ISDESCENDANTNODE(ace, [%s])";
103105
LOG.debug("Query to obtain all ACLs: {}", queryForAClNodes);
104106

105-
for (String path : paths) {
107+
for (String path : rootChildrenPaths) {
106108
if(StringUtils.equals(path, ROOT_REP_POLICY_NODE) || StringUtils.equals(path, ROOT_REPO_POLICY_NODE)) {
107109
continue;
108110
}
109111

110112
String query = String.format(queryForAClNodes, path);
111113

112114
long startTime1 = System.currentTimeMillis();
113-
Set<Node> nodesResult = indexForRepACLExists ?
114-
getNodes(session, query, Query.JCR_SQL2):
115-
getDistinctParentNodes(session, query, Query.JCR_SQL2);
115+
Set<String> nodesResult = indexForRepACLExists ?
116+
getNodePathsFromQuery(session, query, Query.JCR_SQL2):
117+
getDistinctParentNodePathsFromQuery(session, query, Query.JCR_SQL2);
116118
LOG.debug("Query to find ACLs under {} ran in {}ms (count ACLs: {})", path, System.currentTimeMillis()-startTime1, nodesResult.size());
117-
nodes.addAll(nodesResult);
119+
paths.addAll(nodesResult);
118120
}
119121
} catch (Exception e) {
120122
throw new IllegalStateException("Could not query repository for existing ACLs: "+e, e);
121123
}
122-
return nodes;
124+
return paths;
123125
}
124126

125127
/** Get Nodes with XPATH Query. */
126-
public static Set<Node> getNodes(final Session session,
128+
public static Set<String> getNodePathsFromQuery(final Session session,
127129
final String xpathQuery) throws InvalidQueryException,
128130
RepositoryException {
129-
Set<Node> nodes = getNodes(session, xpathQuery, Query.XPATH);
130-
return nodes;
131+
return getNodePathsFromQuery(session, xpathQuery, Query.XPATH);
131132
}
132133

133134

134-
public static Set<Node> getDistinctParentNodes(final Session session,final String queryStatement, String queryLanguageType) throws InvalidQueryException, RepositoryException {
135-
Set<Node> nodes = getNodes(session, queryStatement, queryLanguageType);
136-
Set<Node> parentNodes = new HashSet<>();
135+
public static Set<String> getDistinctParentNodePathsFromQuery(final Session session,final String queryStatement, String queryLanguageType) throws InvalidQueryException, RepositoryException {
136+
Set<String> paths = getNodePathsFromQuery(session, queryStatement, queryLanguageType);
137+
Set<String> parentPaths = new HashSet<>();
137138

138-
for (Node node : nodes) {
139-
parentNodes.add(node.getParent());
139+
for (String path : paths) {
140+
parentPaths.add(Text.getRelativeParent(path, 1));
140141
}
141142

142-
return parentNodes;
143+
return parentPaths;
143144
}
144145

145146

146147
/** @param session the jcr session
147148
* @param queryStatement - ex. "SELECT * FROM [rep:ACL]"
148149
* @param queryLanguageType - ex. Query.JCR_SQL2 */
149-
public static Set<Node> getNodes(final Session session,
150-
final String queryStatement, String queryLanguageType) throws InvalidQueryException,
151-
RepositoryException {
152-
Set<Node> nodes = new HashSet<Node>();
153-
150+
public static NodeIterator getNodesFromQuery(final Session session,
151+
final String queryStatement, String queryLanguageType) throws RepositoryException {
154152
Query query = session.getWorkspace().getQueryManager().createQuery(queryStatement, queryLanguageType);
155153
QueryResult queryResult = query.execute();
156-
NodeIterator nit = queryResult.getNodes();
154+
return queryResult.getNodes();
155+
}
157156

157+
/** @param session the jcr session
158+
* @param queryStatement - ex. "SELECT * FROM [rep:ACL]"
159+
* @param queryLanguageType - ex. Query.JCR_SQL2 */
160+
public static Set<String> getNodePathsFromQuery(final Session session,
161+
final String queryStatement, String queryLanguageType) throws RepositoryException {
162+
Set<String> paths = new HashSet<>();
163+
NodeIterator nit = getNodesFromQuery(session, queryStatement, queryLanguageType);
158164
while (nit.hasNext()) {
159165
// get the next rep:policy node
160166
Node node = nit.nextNode();
161-
nodes.add(node);
167+
paths.add(node.getPath());
162168
}
163-
return nodes;
169+
return paths;
164170
}
165171

166172
public static Set<AclBean> getAuthorizablesAcls(final Session session,
@@ -172,7 +178,7 @@ public static Set<AclBean> getAuthorizablesAcls(final Session session,
172178
StopWatch sw = new StopWatch();
173179
sw.start();
174180

175-
Set<Node> nodeSet = new LinkedHashSet<Node>();
181+
Collection<Node> nodes = new LinkedList<>();
176182

177183
Iterator<String> authorizablesIdIterator = authorizableIds.iterator();
178184

@@ -186,26 +192,30 @@ public static Set<AclBean> getAuthorizablesAcls(final Session session,
186192

187193
String query = queryStringBuilder.toString();
188194

189-
Set<Node> resultNodes = getNodes(session, query, Query.JCR_SQL2);
195+
NodeIterator nit = getNodesFromQuery(session, query, Query.JCR_SQL2);
196+
Collection<Node> resultNodes = new LinkedList<>();
197+
while (nit.hasNext()) {
198+
resultNodes.add(nit.nextNode());
199+
}
190200
LOG.trace("Querying AclBeans with {} returned {} results", query, resultNodes.size());
191-
nodeSet.addAll(resultNodes);
201+
nodes.addAll(resultNodes);
192202
}
193-
Set<AclBean> resultBeans = buildAclBeansFromNodeSet(session, nodeSet, principalIdsToBeFilled);
203+
Set<AclBean> resultBeans = buildAclBeansFromNodes(session, nodes, principalIdsToBeFilled);
194204

195205
sw.stop();
196206
LOG.debug("Found {} AclBeans in {}", resultBeans.size(), msHumanReadable(sw.getTime()));
197207

198208
return resultBeans;
199209
}
200210

201-
private static Set<AclBean> buildAclBeansFromNodeSet(final Session session,
202-
Set<Node> nodeSet, Set<String> principalIdsToBeFilled) throws UnsupportedRepositoryOperationException,
211+
private static Set<AclBean> buildAclBeansFromNodes(final Session session,
212+
Collection<Node> nodes, Set<String> principalIdsToBeFilled) throws UnsupportedRepositoryOperationException,
203213
RepositoryException, PathNotFoundException, AccessDeniedException,
204214
ItemNotFoundException {
205215
AccessControlManager aMgr = session.getAccessControlManager();
206216
AccessControlList acl;
207217
Set<AclBean> aclSet = new TreeSet<AclBean>(); // use natural ordering
208-
for (Node allowOrDenyNode : nodeSet) {
218+
for (Node allowOrDenyNode : nodes) {
209219
String principalId = allowOrDenyNode.getProperty("rep:principalName").getValue().getString();
210220
principalIdsToBeFilled.add(principalId);
211221
Node aclNode = allowOrDenyNode.getParent();

0 commit comments

Comments
 (0)