001/* 002 * Copyright 2016 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.plugins.repository.jcr; 017 018import java.util.Collections; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.Map; 022import java.util.Set; 023import java.util.stream.Collectors; 024 025import javax.jcr.Node; 026import javax.jcr.NodeIterator; 027import javax.jcr.PathNotFoundException; 028import javax.jcr.Repository; 029import javax.jcr.RepositoryException; 030import javax.jcr.Session; 031import javax.jcr.Value; 032import javax.jcr.lock.Lock; 033import javax.jcr.lock.LockManager; 034import javax.jcr.query.Query; 035 036import org.apache.avalon.framework.component.Component; 037import org.apache.avalon.framework.service.ServiceException; 038import org.apache.avalon.framework.service.ServiceManager; 039import org.apache.avalon.framework.service.Serviceable; 040import org.apache.jackrabbit.util.ISO9075; 041import org.apache.jackrabbit.util.Text; 042 043import org.ametys.core.group.GroupIdentity; 044import org.ametys.core.user.UserIdentity; 045import org.ametys.core.util.LambdaUtils; 046import org.ametys.plugins.repository.ACLAmetysObject; 047import org.ametys.plugins.repository.AmetysObjectResolver; 048import org.ametys.plugins.repository.AmetysRepositoryException; 049import org.ametys.plugins.repository.ModifiableACLAmetysObject; 050import org.ametys.plugins.repository.ModifiableACLAmetysObjectProfileAssignmentStorage; 051import org.ametys.plugins.repository.RepositoryConstants; 052import org.ametys.plugins.repository.provider.AbstractRepository; 053import org.ametys.plugins.repository.query.expression.Expression; 054import org.ametys.plugins.repository.query.expression.OrExpression; 055 056/** 057 * Helper for implementing {@link ModifiableACLAmetysObject} in JCR under its node. 058 */ 059public class ACLJCRAmetysObjectHelper implements Component, Serviceable 060{ 061 /** The AmetysObject resolver */ 062 protected static AmetysObjectResolver _resolver; 063 /** The repository */ 064 protected static Repository _repository; 065 066 private static final String __NODE_NAME_ROOT_ACL = RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":acl"; 067 private static final String __NODETYPE_ROOT_ACL = RepositoryConstants.NAMESPACE_PREFIX + ":acl"; 068 069 private static final String __NODE_NAME_ACL_USERS = "users"; 070 private static final String __NODE_NAME_ACL_GROUPS = "groups"; 071 private static final String __NODETYPE_ACL_USER = RepositoryConstants.NAMESPACE_PREFIX + ":acl-user"; 072 private static final String __NODETYPE_ACL_GROUP = RepositoryConstants.NAMESPACE_PREFIX + ":acl-group"; 073 private static final String __NODETYPE_UNSTRUCTURED = "nt:unstructured"; 074 075 private static final String __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":allowed-any-connected-profiles"; 076 private static final String __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":denied-any-connected-profiles"; 077 private static final String __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":allowed-anonymous-profiles"; 078 private static final String __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":denied-anonymous-profiles"; 079 080 private static final String __PROPERTY_NAME_ALLOWED_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":allowed-profiles"; 081 private static final String __PROPERTY_NAME_DENIED_PROFILES = RepositoryConstants.NAMESPACE_PREFIX + ":denied-profiles"; 082 083 @Override 084 public void service(ServiceManager manager) throws ServiceException 085 { 086 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 087 _repository = (Repository) manager.lookup(AbstractRepository.ROLE); 088 } 089 090 091 /* -------------- */ 092 /* HAS PERMISSION */ 093 /* -------------- */ 094 095 private static Set<String> _convertNodeToPath(Set<? extends Object> rootNodes) 096 { 097 return rootNodes.stream().map(JCRAmetysObject.class::cast).map(LambdaUtils.wrap(ao -> ISO9075.encodePath(ao.getNode().getPath()))).collect(Collectors.toSet()); 098 } 099 100 /** 101 * Returns true if any ACL Ametys object has one of the given profiles as denied for the user 102 * @param user The user 103 * @param profileIds The ids of the profiles 104 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 105 * @return true if any ACL Ametys object has one of the given profiles as denied for the user 106 */ 107 public static boolean hasUserDeniedProfile(Set<? extends Object> rootNodes, UserIdentity user, Set<String> profileIds) 108 { 109 Expression expr = new DeniedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 110 for (String rootPath : _convertNodeToPath(rootNodes)) 111 { 112 NodeIterator nodes = getACLUsers(user, rootPath, expr); 113 114 if (nodes.hasNext()) 115 { 116 return true; 117 } 118 } 119 return false; 120 } 121 122 /** 123 * Returns true if any ACL Ametys object has one of the given profiles as allowed for the user 124 * @param user The user 125 * @param profileIds The ids of the profiles 126 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 127 * @return true if any ACL Ametys object has one of the given profiles as allowed for the user 128 */ 129 public static boolean hasUserAllowedProfile(Set<? extends Object> rootNodes, UserIdentity user, Set<String> profileIds) 130 { 131 Expression expr = new AllowedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 132 for (String rootPath : _convertNodeToPath(rootNodes)) 133 { 134 NodeIterator nodes = getACLUsers(user, rootPath, expr); 135 136 if (nodes.hasNext()) 137 { 138 return true; 139 } 140 } 141 return false; 142 } 143 144 /** 145 * Returns true if any ACL Ametys object has one of the given profiles as denied for the group 146 * @param group The group 147 * @param profileIds The ids of the profiles 148 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 149 * @return true if any ACL Ametys object has one of the given profiles as denied for the group 150 */ 151 public static boolean hasGroupDeniedProfile(Set<? extends Object> rootNodes, GroupIdentity group, Set<String> profileIds) 152 { 153 Expression expr = new DeniedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 154 for (String rootPath : _convertNodeToPath(rootNodes)) 155 { 156 NodeIterator nodes = getACLGroups(group, rootPath, expr); 157 158 if (nodes.hasNext()) 159 { 160 return true; 161 } 162 } 163 return false; 164 } 165 166 /** 167 * Returns true if any ACL Ametys object has one of the given profiles as allowed for the group 168 * @param group The group 169 * @param profileIds The ids of the profiles 170 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 171 * @return true if any ACL Ametys object has one of the given profiles as allowed for the group 172 */ 173 public static boolean hasGroupAllowedProfile(Set<? extends Object> rootNodes, GroupIdentity group, Set<String> profileIds) 174 { 175 Expression expr = new AllowedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 176 for (String rootPath : _convertNodeToPath(rootNodes)) 177 { 178 NodeIterator nodes = getACLGroups(group, rootPath, expr); 179 180 if (nodes.hasNext()) 181 { 182 return true; 183 } 184 } 185 return false; 186 } 187 188 /** 189 * Returns true if any ACL Ametys object has one of the given profiles as denied for any connected user 190 * @param profileIds The ids of the profiles 191 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 192 * @return true if any ACL Ametys object has one of the given profiles as denied for any connected user 193 */ 194 public static boolean hasAnyConnectedDeniedProfile(Set<? extends Object> rootNodes, Set<String> profileIds) 195 { 196 Expression expr = new AnyConnectedDeniedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 197 for (String rootPath : _convertNodeToPath(rootNodes)) 198 { 199 NodeIterator nodes = getACLRoots(rootPath, expr); 200 201 if (nodes.hasNext()) 202 { 203 return true; 204 } 205 } 206 return false; 207 } 208 209 /** 210 * Returns true if any ACL Ametys object has one of the given profiles as allowed for any connected user 211 * @param profileIds The ids of the profiles 212 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 213 * @return true if any ACL Ametys object has one of the given profiles as allowed for any connected user 214 */ 215 public static boolean hasAnyConnectedAllowedProfile(Set<? extends Object> rootNodes, Set<String> profileIds) 216 { 217 Expression expr = new AnyConnectedAllowedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 218 for (String rootPath : _convertNodeToPath(rootNodes)) 219 { 220 NodeIterator nodes = getACLRoots(rootPath, expr); 221 222 if (nodes.hasNext()) 223 { 224 return true; 225 } 226 } 227 return false; 228 } 229 230 /** 231 * Returns true if any ACL Ametys object has one of the given profiles as denied for anonymous 232 * @param profileIds The ids of the profiles 233 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 234 * @return true if any ACL Ametys object has one of the given profiles as denied for anonymous 235 */ 236 public static boolean hasAnonymousDeniedProfile(Set<? extends Object> rootNodes, Set<String> profileIds) 237 { 238 Expression expr = new AnonymousDeniedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 239 for (String rootPath : _convertNodeToPath(rootNodes)) 240 { 241 NodeIterator nodes = getACLRoots(rootPath, expr); 242 243 if (nodes.hasNext()) 244 { 245 return true; 246 } 247 } 248 return false; 249 } 250 251 /** 252 * Returns true if any ACL Ametys object has one of the given profiles as allowed for anonymous 253 * @param profileIds The ids of the profiles 254 * @param rootNodes The JCR root nodes where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 255 * @return true if any ACL Ametys object has one of the given profiles as allowed for anonymous 256 */ 257 public static boolean hasAnonymousAllowedProfile(Set<? extends Object> rootNodes, Set<String> profileIds) 258 { 259 Expression expr = new AnonymousAllowedProfileExpression(profileIds.toArray(new String[profileIds.size()])); 260 for (String rootPath : _convertNodeToPath(rootNodes)) 261 { 262 NodeIterator nodes = getACLRoots(rootPath, expr); 263 264 if (nodes.hasNext()) 265 { 266 return true; 267 } 268 } 269 return false; 270 } 271 272 /** 273 * Returns all ACL root objects (ametys:acl nodes) 274 * @param rootPath The root path to restrict the search. Can be null. 275 * @return The ACL root objects 276 */ 277 public static NodeIterator getACLRoots (String rootPath) 278 { 279 return getACLRoots(rootPath, null); 280 } 281 282 /** 283 * Returns all ACL root objects (ametys:acl nodes) 284 * @param rootPath The root path to restrict the search. Can be null. 285 * @param predicat The predicat expression. Can be null. 286 * @return The ACL root objects 287 */ 288 public static NodeIterator getACLRoots (String rootPath, Expression predicat) 289 { 290 StringBuilder sb = new StringBuilder("/jcr:root"); 291 292 if (rootPath != null) 293 { 294 sb.append(rootPath); 295 } 296 297 sb.append("//element(*, ").append(__NODETYPE_ROOT_ACL).append(")"); 298 299 if (predicat != null) 300 { 301 sb.append("[").append(predicat.build()).append("]"); 302 } 303 304 return _query(sb.toString()); 305 } 306 307 /** 308 * Returns all ACL objects for a given user (ametys:acl-user nodes) 309 * @param user The user 310 * @param rootPath The root path to restrict the search. Can be null. 311 * @return The ACL user objects for user 312 */ 313 public static NodeIterator getACLUsers (UserIdentity user, String rootPath) 314 { 315 return getACLUsers(user, rootPath, null); 316 } 317 318 /** 319 * Returns all ACL objects for a given user (ametys:acl-user nodes) 320 * @param user The user 321 * @param rootPath The root path to restrict the search. Can be null. 322 * @param predicat The predicat expression. Can be null. 323 * @return The ACL user objects for user 324 */ 325 public static NodeIterator getACLUsers (UserIdentity user, String rootPath, Expression predicat) 326 { 327 StringBuilder sb = new StringBuilder("/jcr:root"); 328 329 if (rootPath != null) 330 { 331 sb.append(rootPath); 332 } 333 334 sb.append("//element(*, ").append(__NODETYPE_ROOT_ACL).append(")") 335 .append("/").append(__NODE_NAME_ACL_USERS) 336 .append("/").append(user.getPopulationId()) 337 .append("/").append(ISO9075.encode(user.getLogin())); 338 339 if (predicat != null) 340 { 341 sb.append("[").append(predicat.build()).append("]"); 342 } 343 344 String jcrQuery = sb.toString(); 345 return _query(jcrQuery); 346 } 347 348 /** 349 * Returns all ACL objects for users (ametys:acl-user nodes) 350 * @return The ACL user objects for users 351 */ 352 public static NodeIterator getACLUsers () 353 { 354 return getACLUsers(null); 355 } 356 357 /** 358 * Returns all ACL objects for users (ametys:acl-user nodes) 359 * @param predicat The predicat expression. Can be null. 360 * @return The ACL user objects for users 361 */ 362 public static NodeIterator getACLUsers (Expression predicat) 363 { 364 StringBuilder sb = new StringBuilder(); 365 366 sb.append("//element(*, ").append(__NODETYPE_ACL_USER).append(")"); 367 368 if (predicat != null) 369 { 370 sb.append("[").append(predicat.build()).append("]"); 371 } 372 373 return _query(sb.toString()); 374 } 375 376 /** 377 * Returns all ACL objects for groups (ametys:acl-group nodes) 378 * @param predicat The predicat expression. Can be null. 379 * @return The ACL group objects for groups 380 */ 381 public static NodeIterator getACLGroups (Expression predicat) 382 { 383 StringBuilder sb = new StringBuilder(); 384 385 sb.append("//element(*, ").append(__NODETYPE_ACL_GROUP).append(")"); 386 387 if (predicat != null) 388 { 389 sb.append("[").append(predicat.build()).append("]"); 390 } 391 392 return _query(sb.toString()); 393 } 394 395 /** 396 * Returns all ACL objects for a given group (ametys:acl-group nodes) 397 * @param group The group 398 * @param rootPath The root path to restrict the search. Can be null. 399 * @return The ACL user objects for groups 400 */ 401 public static NodeIterator getACLGroups (GroupIdentity group, String rootPath) 402 { 403 return getACLGroups(group, rootPath, null); 404 } 405 406 /** 407 * Returns all ACL objects for a given group (ametys:acl-group nodes) 408 * @param group The group 409 * @param rootPath The root path to restrict the search. Can be null. 410 * @param predicat The predicat expression. Can be null. 411 * @return The ACL user objects for groups 412 */ 413 public static NodeIterator getACLGroups (GroupIdentity group, String rootPath, Expression predicat) 414 { 415 StringBuilder sb = new StringBuilder("/jcr:root"); 416 417 if (rootPath != null) 418 { 419 sb.append(rootPath); 420 } 421 422 sb.append("//element(*, ").append(__NODETYPE_ROOT_ACL).append(")") 423 .append("/").append(__NODE_NAME_ACL_GROUPS) 424 .append("/").append(group.getDirectoryId()) 425 .append("/").append(ISO9075.encode(Text.escapeIllegalJcrChars(group.getId()))); 426 427 if (predicat != null) 428 { 429 sb.append("[").append(predicat.build()).append("]"); 430 } 431 432 return _query(sb.toString()); 433 } 434 435 /** 436 * Returns the allowed profiles for the user on any ACL Ametys object (and not denied on the same object) 437 * @param user The user 438 * @param rootPath The JCR root path where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 439 * @return the allowed profiles for the user on any ACL Ametys object (and not denied on the same object) 440 */ 441 protected static Set<String> _getAllowedProfiles(UserIdentity user, String rootPath) 442 { 443 Set<String> profiles = new HashSet<>(); 444 445 NodeIterator users = getACLUsers(user, rootPath); 446 447 while (users.hasNext()) 448 { 449 Node userNode = (Node) users.next(); 450 451 Set<String> allowedProfiles = _getProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES); 452 Set<String> deniedProfiles = _getProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES); 453 allowedProfiles.removeAll(deniedProfiles); // we want to keep only the not allowed profiles 454 profiles.addAll(allowedProfiles); 455 } 456 457 return profiles; 458 } 459 460 /** 461 * Returns the allowed profiles for the group on any ACL Ametys object (and not denied on the same object) 462 * @param group The group 463 * @param rootPath The JCR root path where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 464 * @return Returns the allowed profiles for the group on any ACL Ametys object (and not denied on the same object) 465 */ 466 protected static Set<String> _getAllowedProfiles(GroupIdentity group, String rootPath) 467 { 468 Set<String> profiles = new HashSet<>(); 469 470 NodeIterator groups = getACLGroups(group, rootPath); 471 472 while (groups.hasNext()) 473 { 474 Node groupNode = (Node) groups.next(); 475 476 Set<String> allowedProfiles = _getProperty(groupNode, __PROPERTY_NAME_ALLOWED_PROFILES); 477 Set<String> deniedProfiles = _getProperty(groupNode, __PROPERTY_NAME_DENIED_PROFILES); 478 allowedProfiles.removeAll(deniedProfiles); // we want to keep only the not allowed profiles 479 profiles.addAll(allowedProfiles); 480 } 481 return profiles; 482 } 483 484 /** 485 * Returns the allowed profiles for any connected user on any ACL Ametys object (and not denied on the same object) 486 * @param rootPath The JCR root path where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 487 * @return the allowed profiles for any connected user on any ACL Ametys object (and not denied on the same object) 488 */ 489 protected static Set<String> _getAnyConnectedAllowedProfiles(String rootPath) 490 { 491 Set<String> profiles = new HashSet<>(); 492 493 NodeIterator objects = getACLRoots(rootPath); 494 while (objects.hasNext()) 495 { 496 Node node = (Node) objects.next(); 497 498 Set<String> allowedProfiles = _getProperty(node, __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES); 499 Set<String> deniedProfiles = _getProperty(node, __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES); 500 allowedProfiles.removeAll(deniedProfiles); // we want to keep only the not allowed profiles 501 profiles.addAll(allowedProfiles); 502 } 503 504 return profiles; 505 } 506 507 /** 508 * Returns the allowed profiles for anonymous on any ACL Ametys object (and not denied on the same object) 509 * @param rootPath The JCR root path where starts the query search (must be something like "//element(myNode, ametys:collection)"), it will be the beginning of the JCR query. Can be null to not restrict the search. 510 * @return the allowed profiles for anonymous on any ACL Ametys object (and not denied on the same object) 511 */ 512 protected static Set<String> _getAnonymousAllowedProfiles(String rootPath) 513 { 514 Set<String> profiles = new HashSet<>(); 515 516 NodeIterator objects = getACLRoots(rootPath); 517 while (objects.hasNext()) 518 { 519 Node node = (Node) objects.next(); 520 521 Set<String> allowedProfiles = _getProperty(node, __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES); 522 Set<String> deniedProfiles = _getProperty(node, __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES); 523 allowedProfiles.removeAll(deniedProfiles); // we want to keep only the not allowed profiles 524 profiles.addAll(allowedProfiles); 525 } 526 527 return profiles; 528 } 529 530 531 private static NodeIterator _query (String jcrQuery) 532 { 533 Session session = null; 534 try 535 { 536 session = _repository.login(); 537 538 @SuppressWarnings("deprecation") 539 Query query = session.getWorkspace().getQueryManager().createQuery(jcrQuery, Query.XPATH); 540 return query.execute().getNodes(); 541 } 542 catch (RepositoryException ex) 543 { 544 if (session != null) 545 { 546 session.logout(); 547 } 548 549 throw new AmetysRepositoryException("An error occured executing the JCR query : " + jcrQuery, ex); 550 } 551 } 552 553 /* --------------------------------------- */ 554 /* ALLOWED PROFILES FOR ANY CONNECTED USER */ 555 /* --------------------------------------- */ 556 557 /** 558 * Helper for {@link ACLAmetysObject#getAllowedProfilesForAnyConnectedUser()} 559 * @param node The JCR node for the Ametys object 560 * @return the allowed profiles any connected user has on the given node 561 */ 562 public static Set<String> getAllowedProfilesForAnyConnectedUser(Node node) 563 { 564 Node aclNode = _getACLNode(node); 565 if (aclNode == null) 566 { 567 return Collections.EMPTY_SET; 568 } 569 else 570 { 571 return _getProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES); 572 } 573 } 574 575 /** 576 * Helper for {@link ModifiableACLAmetysObject#addAllowedProfilesForAnyConnectedUser(Set)} 577 * @param node The JCR node for the Ametys object 578 * @param profileIds The profiles to add 579 */ 580 public static void addAllowedProfilesForAnyConnectedUser(Node node, Set<String> profileIds) 581 { 582 Node aclNode = _getOrCreateACLNode(node); 583 for (String profile : profileIds) 584 { 585 _addProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES, profile); 586 } 587 _save(node); 588 } 589 590 /** 591 * Helper for {@link ModifiableACLAmetysObject#removeAllowedProfilesForAnyConnectedUser(Set)} 592 * @param node The JCR node for the Ametys object 593 * @param profileIds The profiles to remove 594 */ 595 public static void removeAllowedProfilesForAnyConnectedUser(Node node, Set<String> profileIds) 596 { 597 Node aclNode = _getOrCreateACLNode(node); 598 for (String profile : profileIds) 599 { 600 _removeProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES, profile); 601 } 602 _save(node); 603 } 604 605 606 /* -------------------------------------- */ 607 /* DENIED PROFILES FOR ANY CONNECTED USER */ 608 /* -------------------------------------- */ 609 610 /** 611 * Helper for {@link ACLAmetysObject#getDeniedProfilesForAnyConnectedUser()} 612 * @param node The JCR node for the Ametys object 613 * @return the denied profiles any connected user has on the given node 614 */ 615 public static Set<String> getDeniedProfilesForAnyConnectedUser(Node node) 616 { 617 Node aclNode = _getACLNode(node); 618 if (aclNode == null) 619 { 620 return Collections.EMPTY_SET; 621 } 622 else 623 { 624 return _getProperty(aclNode, __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES); 625 } 626 } 627 628 /** 629 * Helper for {@link ModifiableACLAmetysObject#addDeniedProfilesForAnyConnectedUser(Set)} 630 * @param node The JCR node for the Ametys object 631 * @param profileIds The profiles to add 632 */ 633 public static void addDeniedProfilesForAnyConnectedUser(Node node, Set<String> profileIds) 634 { 635 Node aclNode = _getOrCreateACLNode(node); 636 for (String profile : profileIds) 637 { 638 _addProperty(aclNode, __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES, profile); 639 } 640 _save(node); 641 } 642 643 /** 644 * Helper for {@link ModifiableACLAmetysObject#removeDeniedProfilesForAnyConnectedUser(Set)} 645 * @param node The JCR node for the Ametys object 646 * @param profileIds The profiles to remove 647 */ 648 public static void removeDeniedProfilesForAnyConnectedUser(Node node, Set<String> profileIds) 649 { 650 Node aclNode = _getOrCreateACLNode(node); 651 for (String profile : profileIds) 652 { 653 _removeProperty(aclNode, __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES, profile); 654 } 655 _save(node); 656 } 657 658 659 /* ------------------------------ */ 660 /* ALLOWED PROFILES FOR ANONYMOUS */ 661 /* ------------------------------ */ 662 663 /** 664 * Helper for {@link ACLAmetysObject#getAllowedProfilesForAnonymous()} 665 * @param node The JCR node for the Ametys object 666 * @return the allowed profiles an anonymous user has on the given node 667 */ 668 public static Set<String> getAllowedProfilesForAnonymous(Node node) 669 { 670 Node aclNode = _getACLNode(node); 671 if (aclNode == null) 672 { 673 return Collections.EMPTY_SET; 674 } 675 else 676 { 677 return _getProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES); 678 } 679 } 680 681 /** 682 * Helper for {@link ModifiableACLAmetysObject#addAllowedProfilesForAnonymous(Set)} 683 * @param node The JCR node for the Ametys object 684 * @param profileIds The profiles to add 685 */ 686 public static void addAllowedProfilesForAnonymous(Node node, Set<String> profileIds) 687 { 688 Node aclNode = _getOrCreateACLNode(node); 689 for (String profile : profileIds) 690 { 691 _addProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES, profile); 692 } 693 _save(node); 694 } 695 696 /** 697 * Helper for {@link ModifiableACLAmetysObject#removeAllowedProfilesForAnonymous(Set)} 698 * @param node The JCR node for the Ametys object 699 * @param profileIds The profiles to remove 700 */ 701 public static void removeAllowedProfilesForAnonymous(Node node, Set<String> profileIds) 702 { 703 Node aclNode = _getOrCreateACLNode(node); 704 for (String profile : profileIds) 705 { 706 _removeProperty(aclNode, __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES, profile); 707 } 708 _save(node); 709 } 710 711 712 /* ----------------------------- */ 713 /* DENIED PROFILES FOR ANONYMOUS */ 714 /* ----------------------------- */ 715 716 /** 717 * Helper for {@link ACLAmetysObject#getDeniedProfilesForAnonymous()} 718 * @param node The JCR node for the Ametys object 719 * @return the denied profiles an anonymous user has on the given node 720 */ 721 public static Set<String> getDeniedProfilesForAnonymous(Node node) 722 { 723 Node aclNode = _getACLNode(node); 724 if (aclNode == null) 725 { 726 return Collections.EMPTY_SET; 727 } 728 else 729 { 730 return _getProperty(aclNode, __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES); 731 } 732 } 733 734 /** 735 * Helper for {@link ModifiableACLAmetysObject#addDeniedProfilesForAnyConnectedUser(Set)} 736 * @param node The JCR node for the Ametys object 737 * @param profileIds The profiles to add 738 */ 739 public static void addDeniedProfilesForAnonymous(Node node, Set<String> profileIds) 740 { 741 Node aclNode = _getOrCreateACLNode(node); 742 for (String profile : profileIds) 743 { 744 _addProperty(aclNode, __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES, profile); 745 } 746 _save(node); 747 } 748 749 /** 750 * Helper for {@link ModifiableACLAmetysObject#removeDeniedProfilesForAnyConnectedUser(Set)} 751 * @param node The JCR node for the Ametys object 752 * @param profileIds The profiles to remove 753 */ 754 public static void removeDeniedProfilesForAnonymous(Node node, Set<String> profileIds) 755 { 756 Node aclNode = _getOrCreateACLNode(node); 757 for (String profile : profileIds) 758 { 759 _removeProperty(aclNode, __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES, profile); 760 } 761 _save(node); 762 } 763 764 765 /* --------------------------- */ 766 /* MANAGEMENT OF ALLOWED USERS */ 767 /* --------------------------- */ 768 /** 769 * Helper for {@link ACLAmetysObject#getAllowedProfilesForUser(UserIdentity)} 770 * @param node The JCR node for the Ametys object 771 * @param user The user 772 * @return The denied profiles 773 */ 774 public static Set<String> getAllowedProfilesForUser (Node node, UserIdentity user) 775 { 776 Node userNode = _getUserNode(node, user); 777 if (userNode == null) 778 { 779 return new HashSet<>(); 780 } 781 782 return _getProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES); 783 } 784 785 /** 786 * Helper for {@link ACLAmetysObject#getAllowedProfilesForUsers()} 787 * @param node The JCR node for the Ametys object 788 * @return The map of allowed users (keys) with their assigned profiles (values) 789 */ 790 public static Map<UserIdentity, Set<String>> getAllowedProfilesForUsers(Node node) 791 { 792 Map<UserIdentity, Set<String>> result = new HashMap<>(); 793 794 try 795 { 796 Node usersNode = _getUsersNode(node); 797 if (usersNode == null) 798 { 799 return result; 800 } 801 802 NodeIterator populationsIterator = usersNode.getNodes(); 803 while (populationsIterator.hasNext()) 804 { 805 Node population = populationsIterator.nextNode(); 806 NodeIterator usersIterator = population.getNodes(); 807 while (usersIterator.hasNext()) 808 { 809 Node user = usersIterator.nextNode(); 810 Set<String> allowedProfiles = _getProperty(user, __PROPERTY_NAME_ALLOWED_PROFILES); 811 if (!allowedProfiles.isEmpty()) 812 { 813 result.put(new UserIdentity(user.getName(), population.getName()), allowedProfiles); 814 } 815 } 816 } 817 } 818 catch (RepositoryException e) 819 { 820 throw new AmetysRepositoryException("Unable to get allowed users", e); 821 } 822 return result; 823 } 824 825 /** 826 * Helper for {@link ACLAmetysObject#getAllowedUsers(String)} 827 * @param node The JCR node for the Ametys object 828 * @param profileId The id of the profile 829 * @return The allowed users with that profile on that ametys object 830 */ 831 public static Set<UserIdentity> getAllowedUsers(Node node, String profileId) 832 { 833 try 834 { 835 Set<UserIdentity> allowedUsers = new HashSet<>(); 836 837 Node usersNode = _getUsersNode(node); 838 if (usersNode == null) 839 { 840 return allowedUsers; 841 } 842 843 NodeIterator popNodes = usersNode.getNodes(); 844 845 while (popNodes.hasNext()) 846 { 847 Node popNode = (Node) popNodes.next(); 848 849 NodeIterator userNodes = popNode.getNodes(); 850 851 while (userNodes.hasNext()) 852 { 853 Node userNode = (Node) userNodes.next(); 854 Set<String> allowedProfiles = _getProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES); 855 if (allowedProfiles.contains(profileId)) 856 { 857 allowedUsers.add(new UserIdentity(userNode.getName(), popNode.getName())); 858 } 859 } 860 } 861 862 return allowedUsers; 863 864 /*Expression expr = new AllowedProfileExpression(profileId); 865 AmetysObjectIterable<JCRAmetysObject> users = getACLUsers(node, expr); 866 867 return users.stream() 868 .map(LambdaUtils.wrap(aclUser -> new UserIdentity(aclUser.getName(), aclUser.getNode().getParent().getName()))) 869 .collect(Collectors.toSet());*/ 870 } 871 catch (RepositoryException e) 872 { 873 throw new AmetysRepositoryException(e); 874 } 875 } 876 877 /** 878 * Helper for {@link ModifiableACLAmetysObject#addAllowedUsers(Set, String)} 879 * @param users The users to add 880 * @param node The JCR node for the Ametys object 881 * @param profileId The id of the profile 882 */ 883 public static void addAllowedUsers(Set<UserIdentity> users, Node node, String profileId) 884 { 885 for (UserIdentity userIdentity : users) 886 { 887 Node userNode = _getOrCreateUserNode(node, userIdentity); 888 _addProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 889 } 890 _save(node); 891 } 892 893 /** 894 * Helper for {@link ModifiableACLAmetysObject#removeAllowedUsers(Set, String)} 895 * @param users The users to remove 896 * @param node The JCR node for the Ametys object 897 * @param profileId The id of the profile 898 */ 899 public static void removeAllowedUsers(Set<UserIdentity> users, Node node, String profileId) 900 { 901 for (UserIdentity userIdentity : users) 902 { 903 Node userNode = _getOrCreateUserNode(node, userIdentity); 904 _removeProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 905 } 906 _save(node); 907 } 908 909 /** 910 * Helper for {@link ModifiableACLAmetysObject#removeAllowedGroups(Set)} 911 * @param users The users to remove 912 * @param node The JCR node for the Ametys object 913 */ 914 public static void removeAllowedUsers(Set<UserIdentity> users, Node node) 915 { 916 for (UserIdentity userIdentity : users) 917 { 918 Node userNode = _getOrCreateUserNode(node, userIdentity); 919 _setProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES, Collections.EMPTY_SET); 920 } 921 _save(node); 922 } 923 924 925 /* ---------------------------- */ 926 /* MANAGEMENT OF ALLOWED GROUPS */ 927 /* ---------------------------- */ 928 929 /** 930 * Helper for {@link ACLAmetysObject#getAllowedProfilesForGroups()} 931 * @param node The JCR node for the Ametys object 932 * @return The map of allowed groups (keys) with their assigned profiles (values) 933 */ 934 public static Map<GroupIdentity, Set<String>> getAllowedProfilesForGroups(Node node) 935 { 936 Map<GroupIdentity, Set<String>> result = new HashMap<>(); 937 938 try 939 { 940 Node groupsNode = _getGroupsNode(node); 941 if (groupsNode == null) 942 { 943 return result; 944 } 945 946 NodeIterator groupDirectoriesIterator = groupsNode.getNodes(); 947 while (groupDirectoriesIterator.hasNext()) 948 { 949 Node groupDirectory = groupDirectoriesIterator.nextNode(); 950 NodeIterator groupsIterator = groupDirectory.getNodes(); 951 while (groupsIterator.hasNext()) 952 { 953 Node group = groupsIterator.nextNode(); 954 Set<String> allowedProfiles = _getProperty(group, __PROPERTY_NAME_ALLOWED_PROFILES); 955 if (!allowedProfiles.isEmpty()) 956 { 957 result.put(new GroupIdentity(Text.unescapeIllegalJcrChars(group.getName()), groupDirectory.getName()), allowedProfiles); 958 } 959 } 960 } 961 } 962 catch (RepositoryException e) 963 { 964 throw new AmetysRepositoryException("Unable to get allowed groups", e); 965 } 966 return result; 967 } 968 969 /** 970 * Helper for {@link ACLAmetysObject#getAllowedGroups(String)} 971 * @param node The JCR node for the Ametys object 972 * @param profileId The id of the profile 973 * @return The allowed groups with that profile on that ametys object 974 */ 975 public static Set<GroupIdentity> getAllowedGroups(Node node, String profileId) 976 { 977 try 978 { 979 Set<GroupIdentity> deniedGroups = new HashSet<>(); 980 981 Node groupsNode = _getGroupsNode(node); 982 if (groupsNode == null) 983 { 984 return deniedGroups; 985 } 986 987 NodeIterator gpDirNodes = groupsNode.getNodes(); 988 989 while (gpDirNodes.hasNext()) 990 { 991 Node gpDirNode = (Node) gpDirNodes.next(); 992 993 NodeIterator gpNodes = gpDirNode.getNodes(); 994 995 while (gpNodes.hasNext()) 996 { 997 Node gpNode = (Node) gpNodes.next(); 998 Set<String> allowedProfiles = _getProperty(gpNode, __PROPERTY_NAME_ALLOWED_PROFILES); 999 if (allowedProfiles.contains(profileId)) 1000 { 1001 deniedGroups.add(new GroupIdentity(gpNode.getName(), gpDirNode.getName())); 1002 } 1003 } 1004 } 1005 1006 return deniedGroups; 1007 1008 /*Expression expr = new AllowedProfileExpression(profileId); 1009 AmetysObjectIterable<JCRAmetysObject> groups = getACLGroups(node, expr); 1010 1011 return groups.stream() 1012 .map(LambdaUtils.wrap(aclGroup -> new GroupIdentity(aclGroup.getName(), aclGroup.getNode().getParent().getName()))) 1013 .collect(Collectors.toSet());*/ 1014 } 1015 catch (RepositoryException e) 1016 { 1017 throw new AmetysRepositoryException(e); 1018 } 1019 } 1020 1021 /** 1022 * Helper for {@link ModifiableACLAmetysObject#addAllowedGroups(Set, String)} 1023 * @param groups The groups to add 1024 * @param node The JCR node for the Ametys object 1025 * @param profileId The id of the profile 1026 */ 1027 public static void addAllowedGroups(Set<GroupIdentity> groups, Node node, String profileId) 1028 { 1029 for (GroupIdentity groupIdentity : groups) 1030 { 1031 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1032 _addProperty(groupNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 1033 } 1034 _save(node); 1035 } 1036 1037 /** 1038 * Helper for {@link ModifiableACLAmetysObject#removeAllowedGroups(Set, String)} 1039 * @param groups The groups to remove 1040 * @param node The JCR node for the Ametys object 1041 * @param profileId The id of the profile 1042 */ 1043 public static void removeAllowedGroups(Set<GroupIdentity> groups, Node node, String profileId) 1044 { 1045 for (GroupIdentity groupIdentity : groups) 1046 { 1047 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1048 _removeProperty(groupNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 1049 } 1050 _save(node); 1051 } 1052 1053 /** 1054 * Helper for {@link ModifiableACLAmetysObject#removeAllowedGroups(Set)} 1055 * @param groups The groups to remove 1056 * @param node The JCR node for the Ametys object 1057 */ 1058 public static void removeAllowedGroups(Set<GroupIdentity> groups, Node node) 1059 { 1060 for (GroupIdentity groupIdentity : groups) 1061 { 1062 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1063 _setProperty(groupNode, __PROPERTY_NAME_ALLOWED_PROFILES, Collections.EMPTY_SET); 1064 } 1065 _save(node); 1066 } 1067 1068 1069 /* ---------------------------- */ 1070 /* MANAGEMENT OF DENIED USERS */ 1071 /* ---------------------------- */ 1072 /** 1073 * Helper for {@link ACLAmetysObject#getDeniedProfilesForUser(UserIdentity)} 1074 * @param node The JCR node for the Ametys object 1075 * @param user The user 1076 * @return The denied profiles 1077 */ 1078 public static Set<String> getDeniedProfilesForUser (Node node, UserIdentity user) 1079 { 1080 Node userNode = _getUserNode(node, user); 1081 if (userNode == null) 1082 { 1083 return new HashSet<>(); 1084 } 1085 1086 return _getProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES); 1087 } 1088 1089 /** 1090 * Helper for {@link ACLAmetysObject#getDeniedProfilesForUsers()} 1091 * @param node The JCR node for the Ametys object 1092 * @return The map of denied users (keys) with their assigned profiles (values) 1093 */ 1094 public static Map<UserIdentity, Set<String>> getDeniedProfilesForUsers(Node node) 1095 { 1096 Map<UserIdentity, Set<String>> result = new HashMap<>(); 1097 1098 try 1099 { 1100 Node usersNode = _getUsersNode(node); 1101 if (usersNode == null) 1102 { 1103 return result; 1104 } 1105 1106 NodeIterator populationsIterator = usersNode.getNodes(); 1107 while (populationsIterator.hasNext()) 1108 { 1109 Node population = populationsIterator.nextNode(); 1110 NodeIterator usersIterator = population.getNodes(); 1111 while (usersIterator.hasNext()) 1112 { 1113 Node user = usersIterator.nextNode(); 1114 Set<String> allowedProfiles = _getProperty(user, __PROPERTY_NAME_DENIED_PROFILES); 1115 if (!allowedProfiles.isEmpty()) 1116 { 1117 result.put(new UserIdentity(user.getName(), population.getName()), allowedProfiles); 1118 } 1119 } 1120 } 1121 } 1122 catch (RepositoryException e) 1123 { 1124 throw new AmetysRepositoryException("Unable to get denied users", e); 1125 } 1126 return result; 1127 } 1128 1129 /** 1130 * Helper for {@link ACLAmetysObject#getDeniedUsers(String)} 1131 * @param node The JCR node for the Ametys object 1132 * @param profileId The id of the profile 1133 * @return The denied users with that profile on that ametys object 1134 */ 1135 public static Set<UserIdentity> getDeniedUsers(Node node, String profileId) 1136 { 1137 1138 try 1139 { 1140 Set<UserIdentity> deniedUsers = new HashSet<>(); 1141 1142 Node usersNode = _getUsersNode(node); 1143 if (usersNode == null) 1144 { 1145 return deniedUsers; 1146 } 1147 1148 NodeIterator popNodes = usersNode.getNodes(); 1149 while (popNodes.hasNext()) 1150 { 1151 Node popNode = (Node) popNodes.next(); 1152 1153 NodeIterator userNodes = popNode.getNodes(); 1154 1155 while (userNodes.hasNext()) 1156 { 1157 Node userNode = (Node) userNodes.next(); 1158 Set<String> allowedProfiles = _getProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES); 1159 if (allowedProfiles.contains(profileId)) 1160 { 1161 deniedUsers.add(new UserIdentity(userNode.getName(), popNode.getName())); 1162 } 1163 } 1164 } 1165 1166 return deniedUsers; 1167 1168 /*Expression expr = new DeniedProfileExpression(profileId); 1169 AmetysObjectIterable<JCRAmetysObject> users = getACLUsers(node, expr); 1170 1171 return users.stream() 1172 .map(LambdaUtils.wrap(aclUser -> new UserIdentity(aclUser.getName(), aclUser.getNode().getParent().getName()))) 1173 .collect(Collectors.toSet());*/ 1174 } 1175 catch (RepositoryException e) 1176 { 1177 throw new AmetysRepositoryException(e); 1178 } 1179 } 1180 1181 /** 1182 * Helper for {@link ModifiableACLAmetysObject#addDeniedUsers(Set, String)} 1183 * @param users The users to add 1184 * @param node The JCR node for the Ametys object 1185 * @param profileId The id of the profile 1186 */ 1187 public static void addDeniedUsers(Set<UserIdentity> users, Node node, String profileId) 1188 { 1189 for (UserIdentity userIdentity : users) 1190 { 1191 Node userNode = _getOrCreateUserNode(node, userIdentity); 1192 _addProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1193 } 1194 _save(node); 1195 } 1196 1197 /** 1198 * Helper for {@link ModifiableACLAmetysObject#removeDeniedUsers(Set, String)} 1199 * @param users The users to remove 1200 * @param node The JCR node for the Ametys object 1201 * @param profileId The id of the profile 1202 */ 1203 public static void removeDeniedUsers(Set<UserIdentity> users, Node node, String profileId) 1204 { 1205 for (UserIdentity userIdentity : users) 1206 { 1207 Node userNode = _getOrCreateUserNode(node, userIdentity); 1208 _removeProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1209 } 1210 _save(node); 1211 } 1212 1213 /** 1214 * Helper for {@link ModifiableACLAmetysObject#removeDeniedUsers(Set)} 1215 * @param users The users to remove 1216 * @param node The JCR node for the Ametys object 1217 */ 1218 public static void removeDeniedUsers(Set<UserIdentity> users, Node node) 1219 { 1220 for (UserIdentity userIdentity : users) 1221 { 1222 Node userNode = _getOrCreateUserNode(node, userIdentity); 1223 _setProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES, Collections.EMPTY_SET); 1224 } 1225 _save(node); 1226 } 1227 1228 1229 /* ----------------------------- */ 1230 /* MANAGEMENT OF DENIED GROUPS */ 1231 /* ----------------------------- */ 1232 1233 /** 1234 * Helper for {@link ACLAmetysObject#getDeniedProfilesForGroups()} 1235 * @param node The JCR node for the Ametys object 1236 * @return The map of denied groups (keys) with their assigned profiles (values) 1237 */ 1238 public static Map<GroupIdentity, Set<String>> getDeniedProfilesForGroups(Node node) 1239 { 1240 Map<GroupIdentity, Set<String>> result = new HashMap<>(); 1241 1242 try 1243 { 1244 Node groupsNode = _getGroupsNode(node); 1245 if (groupsNode == null) 1246 { 1247 return result; 1248 } 1249 1250 NodeIterator groupDirectoriesIterator = groupsNode.getNodes(); 1251 while (groupDirectoriesIterator.hasNext()) 1252 { 1253 Node groupDirectory = groupDirectoriesIterator.nextNode(); 1254 NodeIterator groupsIterator = groupDirectory.getNodes(); 1255 while (groupsIterator.hasNext()) 1256 { 1257 Node group = groupsIterator.nextNode(); 1258 Set<String> allowedProfiles = _getProperty(group, __PROPERTY_NAME_DENIED_PROFILES); 1259 if (!allowedProfiles.isEmpty()) 1260 { 1261 result.put(new GroupIdentity(group.getName(), groupDirectory.getName()), allowedProfiles); 1262 } 1263 } 1264 } 1265 } 1266 catch (RepositoryException e) 1267 { 1268 throw new AmetysRepositoryException("Unable to get allowed groups", e); 1269 } 1270 return result; 1271 } 1272 1273 /** 1274 * Helper for {@link ACLAmetysObject#getDeniedGroups(String)} 1275 * @param node The JCR node for the Ametys object 1276 * @param profileId The id of the profile 1277 * @return The denied groups with that profile on that ametys object 1278 */ 1279 public static Set<GroupIdentity> getDeniedGroups(Node node, String profileId) 1280 { 1281 try 1282 { 1283 Set<GroupIdentity> deniedGroups = new HashSet<>(); 1284 1285 Node groupsNode = _getGroupsNode(node); 1286 if (groupsNode == null) 1287 { 1288 return deniedGroups; 1289 } 1290 1291 NodeIterator gpDirNodes = groupsNode.getNodes(); 1292 1293 while (gpDirNodes.hasNext()) 1294 { 1295 Node gpDirNode = (Node) gpDirNodes.next(); 1296 1297 NodeIterator gpNodes = gpDirNode.getNodes(); 1298 1299 while (gpNodes.hasNext()) 1300 { 1301 Node gpNode = (Node) gpNodes.next(); 1302 Set<String> allowedProfiles = _getProperty(gpNode, __PROPERTY_NAME_DENIED_PROFILES); 1303 if (allowedProfiles.contains(profileId)) 1304 { 1305 deniedGroups.add(new GroupIdentity(gpNode.getName(), gpDirNode.getName())); 1306 } 1307 } 1308 } 1309 1310 return deniedGroups; 1311 1312 /*Expression expr = new DeniedProfileExpression(profileId); 1313 AmetysObjectIterable<JCRAmetysObject> groups = getACLGroups(node, expr); 1314 1315 return groups.stream() 1316 .map(LambdaUtils.wrap(aclGroup -> new GroupIdentity(aclGroup.getName(), aclGroup.getNode().getParent().getName()))) 1317 .collect(Collectors.toSet());*/ 1318 } 1319 catch (RepositoryException e) 1320 { 1321 throw new AmetysRepositoryException(e); 1322 } 1323 } 1324 1325 /** 1326 * Helper for {@link ModifiableACLAmetysObject#addDeniedGroups(Set, String)} 1327 * @param groups The groups to add 1328 * @param node The JCR node for the Ametys object 1329 * @param profileId The id of the profile 1330 */ 1331 public static void addDeniedGroups(Set<GroupIdentity> groups, Node node, String profileId) 1332 { 1333 for (GroupIdentity groupIdentity : groups) 1334 { 1335 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1336 _addProperty(groupNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1337 } 1338 _save(node); 1339 } 1340 1341 /** 1342 * Helper for {@link ModifiableACLAmetysObject#removeDeniedGroups(Set, String)} 1343 * @param groups The groups to remove 1344 * @param node The JCR node for the Ametys object 1345 * @param profileId The id of the profile 1346 */ 1347 public static void removeDeniedGroups(Set<GroupIdentity> groups, Node node, String profileId) 1348 { 1349 for (GroupIdentity groupIdentity : groups) 1350 { 1351 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1352 _removeProperty(groupNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1353 } 1354 _save(node); 1355 } 1356 1357 /** 1358 * Helper for {@link ModifiableACLAmetysObject#removeDeniedGroups(Set)} 1359 * @param groups The groups to remove 1360 * @param node The JCR node for the Ametys object 1361 */ 1362 public static void removeDeniedGroups(Set<GroupIdentity> groups, Node node) 1363 { 1364 for (GroupIdentity groupIdentity : groups) 1365 { 1366 Node groupNode = _getOrCreateGroupNode(node, groupIdentity); 1367 _setProperty(groupNode, __PROPERTY_NAME_DENIED_PROFILES, Collections.EMPTY_SET); 1368 } 1369 _save(node); 1370 } 1371 1372 1373 /* ------ */ 1374 /* REMOVE */ 1375 /* ------ */ 1376 1377 /** 1378 * Helper for {@link ModifiableACLAmetysObjectProfileAssignmentStorage#removeProfile(String)} 1379 * @param profileId The id of the profile 1380 */ 1381 public static void removeProfile(String profileId) 1382 { 1383 // Remove this profile set as allowed or denied in users 1384 Expression expr = new OrExpression(new AllowedProfileExpression(profileId), new DeniedProfileExpression(profileId)); 1385 NodeIterator users = getACLUsers(expr); 1386 while (users.hasNext()) 1387 { 1388 Node userNode = (Node) users.next(); 1389 _removeProperty(userNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 1390 _removeProperty(userNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1391 _save(userNode); 1392 } 1393 1394 // Remove this profile set as allowed or denied in groups 1395 NodeIterator groups = getACLGroups(expr); 1396 while (groups.hasNext()) 1397 { 1398 Node groupNode = (Node) groups.next(); 1399 _removeProperty(groupNode, __PROPERTY_NAME_ALLOWED_PROFILES, profileId); 1400 _removeProperty(groupNode, __PROPERTY_NAME_DENIED_PROFILES, profileId); 1401 _save(groupNode); 1402 } 1403 1404 // Remove this profile set as allowed or denied for anonymous and any connected 1405 expr = new OrExpression(new AnonymousAllowedProfileExpression(profileId), new AnonymousDeniedProfileExpression(profileId), new AnyConnectedAllowedProfileExpression(profileId), new AnyConnectedDeniedProfileExpression(profileId)); 1406 NodeIterator nodes = getACLRoots(null, expr); 1407 while (nodes.hasNext()) 1408 { 1409 Node node = (Node) nodes.next(); 1410 _removeProperty(node, __PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES, profileId); 1411 _removeProperty(node, __PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES, profileId); 1412 _removeProperty(node, __PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES, profileId); 1413 _removeProperty(node, __PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES, profileId); 1414 _save(node); 1415 } 1416 } 1417 1418 /** 1419 * Helper for {@link ModifiableACLAmetysObjectProfileAssignmentStorage#removeUser(UserIdentity)} 1420 * @param user The user 1421 */ 1422 public static void removeUser(UserIdentity user) 1423 { 1424 NodeIterator users = getACLUsers(user, null); 1425 1426 while (users.hasNext()) 1427 { 1428 Node userNode = (Node) users.next(); 1429 try 1430 { 1431 userNode.remove(); 1432 _save(userNode); 1433 } 1434 catch (RepositoryException e) 1435 { 1436 throw new AmetysRepositoryException(e); 1437 } 1438 } 1439 } 1440 1441 /** 1442 * Helper for {@link ModifiableACLAmetysObjectProfileAssignmentStorage#removeGroup(GroupIdentity)} 1443 * @param group The group 1444 */ 1445 public static void removeGroup(GroupIdentity group) 1446 { 1447 NodeIterator groups = getACLGroups(group, null); 1448 while (groups.hasNext()) 1449 { 1450 Node gpNode = (Node) groups.next(); 1451 try 1452 { 1453 gpNode.remove(); 1454 _save(gpNode); 1455 } 1456 catch (RepositoryException e) 1457 { 1458 throw new AmetysRepositoryException(e); 1459 } 1460 } 1461 } 1462 1463 1464 /* --------------- */ 1465 /* PRIVATE METHODS */ 1466 /* --------------- */ 1467 1468 private static void _checkLock(Node node) throws AmetysRepositoryException 1469 { 1470 try 1471 { 1472 if (node.isLocked()) 1473 { 1474 LockManager lockManager = node.getSession().getWorkspace().getLockManager(); 1475 1476 Lock lock = lockManager.getLock(node.getPath()); 1477 Node lockHolder = lock.getNode(); 1478 1479 lockManager.addLockToken(lockHolder.getProperty(RepositoryConstants.METADATA_LOCKTOKEN).getString()); 1480 } 1481 } 1482 catch (RepositoryException e) 1483 { 1484 throw new AmetysRepositoryException("Unable to add lock token on ACL node", e); 1485 } 1486 } 1487 1488 private static Node _getOrCreateACLNode(Node node) 1489 { 1490 try 1491 { 1492 if (node.hasNode(__NODE_NAME_ROOT_ACL)) 1493 { 1494 return node.getNode(__NODE_NAME_ROOT_ACL); 1495 } 1496 else 1497 { 1498 _checkLock(node); 1499 return node.addNode(__NODE_NAME_ROOT_ACL, __NODETYPE_ROOT_ACL); 1500 } 1501 } 1502 catch (RepositoryException e) 1503 { 1504 throw new AmetysRepositoryException("Error while getting root ACL node.", e); 1505 } 1506 } 1507 1508 private static Node _getACLNode(Node node) 1509 { 1510 try 1511 { 1512 if (node.hasNode(__NODE_NAME_ROOT_ACL)) 1513 { 1514 return node.getNode(__NODE_NAME_ROOT_ACL); 1515 } 1516 else 1517 { 1518 return null; 1519 } 1520 } 1521 catch (RepositoryException e) 1522 { 1523 throw new AmetysRepositoryException("Error while getting root ACL node.", e); 1524 } 1525 } 1526 1527 private static Node _getOrCreateUsersNode(Node node) 1528 { 1529 try 1530 { 1531 Node aclNode = _getOrCreateACLNode(node); 1532 if (aclNode.hasNode(__NODE_NAME_ACL_USERS)) 1533 { 1534 return aclNode.getNode(__NODE_NAME_ACL_USERS); 1535 } 1536 else 1537 { 1538 return aclNode.addNode(__NODE_NAME_ACL_USERS, __NODETYPE_UNSTRUCTURED); 1539 } 1540 } 1541 catch (RepositoryException e) 1542 { 1543 throw new AmetysRepositoryException("Error while getting 'users' ACL node.", e); 1544 } 1545 } 1546 1547 private static Node _getUserNode(Node node, UserIdentity user) 1548 { 1549 try 1550 { 1551 Node aclNode = _getACLNode(node); 1552 if (aclNode != null && aclNode.hasNode(__NODE_NAME_ACL_USERS)) 1553 { 1554 Node aclUsersNode = aclNode.getNode(__NODE_NAME_ACL_USERS); 1555 if (aclUsersNode.hasNode(user.getPopulationId())) 1556 { 1557 Node popNode = aclUsersNode.getNode(user.getPopulationId()); 1558 if (popNode.hasNode(user.getLogin())) 1559 { 1560 return popNode.getNode(user.getLogin()); 1561 } 1562 } 1563 } 1564 1565 return null; 1566 } 1567 catch (RepositoryException e) 1568 { 1569 throw new AmetysRepositoryException("Error while getting 'users' ACL node.", e); 1570 } 1571 } 1572 1573 private static Node _getUsersNode(Node node) 1574 { 1575 try 1576 { 1577 Node aclNode = _getACLNode(node); 1578 if (aclNode != null && aclNode.hasNode(__NODE_NAME_ACL_USERS)) 1579 { 1580 return aclNode.getNode(__NODE_NAME_ACL_USERS); 1581 } 1582 else 1583 { 1584 return null; 1585 } 1586 } 1587 catch (RepositoryException e) 1588 { 1589 throw new AmetysRepositoryException("Error while getting 'users' ACL node.", e); 1590 } 1591 } 1592 1593 private static Node _getOrCreateGroupsNode(Node node) 1594 { 1595 try 1596 { 1597 Node aclNode = _getOrCreateACLNode(node); 1598 if (aclNode.hasNode(__NODE_NAME_ACL_GROUPS)) 1599 { 1600 return aclNode.getNode(__NODE_NAME_ACL_GROUPS); 1601 } 1602 else 1603 { 1604 return aclNode.addNode(__NODE_NAME_ACL_GROUPS, __NODETYPE_UNSTRUCTURED); 1605 } 1606 } 1607 catch (RepositoryException e) 1608 { 1609 throw new AmetysRepositoryException("Error while getting 'groups' ACL node.", e); 1610 } 1611 } 1612 1613 private static Node _getGroupsNode(Node node) 1614 { 1615 try 1616 { 1617 Node aclNode = _getACLNode(node); 1618 if (aclNode != null && aclNode.hasNode(__NODE_NAME_ACL_GROUPS)) 1619 { 1620 return aclNode.getNode(__NODE_NAME_ACL_GROUPS); 1621 } 1622 else 1623 { 1624 return null; 1625 } 1626 } 1627 catch (RepositoryException e) 1628 { 1629 throw new AmetysRepositoryException("Error while getting 'groups' ACL node.", e); 1630 } 1631 } 1632 1633 private static Node _getOrCreateUserNode(Node node, UserIdentity userIdentity) 1634 { 1635 try 1636 { 1637 Node usersNode = _getOrCreateUsersNode(node); 1638 String population = userIdentity.getPopulationId(); 1639 String login = userIdentity.getLogin(); 1640 1641 if (usersNode.hasNode(population)) 1642 { 1643 Node populationNode = usersNode.getNode(population); 1644 if (populationNode.hasNode(login)) 1645 { 1646 return populationNode.getNode(login); 1647 } 1648 else 1649 { 1650 return populationNode.addNode(login, __NODETYPE_ACL_USER); 1651 } 1652 } 1653 else 1654 { 1655 return usersNode.addNode(population, __NODETYPE_UNSTRUCTURED).addNode(login, __NODETYPE_ACL_USER); 1656 } 1657 } 1658 catch (RepositoryException e) 1659 { 1660 throw new AmetysRepositoryException(String.format("Error while getting 'user' ACL node for %s.", userIdentity.toString()), e); 1661 } 1662 } 1663 1664 private static Node _getOrCreateGroupNode(Node node, GroupIdentity groupIdentity) 1665 { 1666 try 1667 { 1668 Node groupsNode = _getOrCreateGroupsNode(node); 1669 String directoryId = groupIdentity.getDirectoryId(); 1670 String id = Text.escapeIllegalJcrChars(groupIdentity.getId()); 1671 1672 if (groupsNode.hasNode(directoryId)) 1673 { 1674 Node populationNode = groupsNode.getNode(directoryId); 1675 if (populationNode.hasNode(id)) 1676 { 1677 return populationNode.getNode(id); 1678 } 1679 else 1680 { 1681 return populationNode.addNode(id, __NODETYPE_ACL_GROUP); 1682 } 1683 } 1684 else 1685 { 1686 return groupsNode.addNode(directoryId, __NODETYPE_UNSTRUCTURED).addNode(Text.escapeIllegalJcrChars(id), __NODETYPE_ACL_GROUP); 1687 } 1688 } 1689 catch (RepositoryException e) 1690 { 1691 throw new AmetysRepositoryException(String.format("Error while getting 'group' ACL node for %s.", groupIdentity.toString()), e); 1692 } 1693 } 1694 1695 private static Set<String> _getProperty(Node node, String propertyName) 1696 { 1697 try 1698 { 1699 Value[] values = node.getProperty(propertyName).getValues(); 1700 Set<String> result = new HashSet<>(); 1701 for (Value value : values) 1702 { 1703 result.add(value.getString()); 1704 } 1705 return result; 1706 } 1707 catch (PathNotFoundException e) 1708 { 1709 return new HashSet<>(); 1710 } 1711 catch (RepositoryException e) 1712 { 1713 throw new AmetysRepositoryException("Unable to get " + propertyName + " property", e); 1714 } 1715 } 1716 1717 private static void _setProperty(Node node, String propertyName, Set<String> profiles) 1718 { 1719 try 1720 { 1721 node.setProperty(propertyName, profiles.toArray(new String[profiles.size()])); 1722 } 1723 catch (RepositoryException e) 1724 { 1725 throw new AmetysRepositoryException("Unable to set " + propertyName + " property", e); 1726 } 1727 } 1728 1729 private static void _addProperty(Node node, String propertyName, String profileToAdd) 1730 { 1731 Set<String> profiles = _getProperty(node, propertyName); 1732 if (!profiles.contains(profileToAdd)) 1733 { 1734 profiles.add(profileToAdd); 1735 _setProperty(node, propertyName, profiles); 1736 } 1737 } 1738 1739 private static void _removeProperty(Node node, String propertyName, String profileToRemove) 1740 { 1741 Set<String> profiles = _getProperty(node, propertyName); 1742 if (profiles.contains(profileToRemove)) 1743 { 1744 profiles.remove(profileToRemove); 1745 _setProperty(node, propertyName, profiles); 1746 } 1747 } 1748 1749 private static void _save(Node node) 1750 { 1751 try 1752 { 1753 node.getSession().save(); 1754 } 1755 catch (RepositoryException e) 1756 { 1757 throw new AmetysRepositoryException("Unable to save changes", e); 1758 } 1759 } 1760 1761 /* ---------------------------------------*/ 1762 /* JCR EXPRESSIONS FOR PROFILES */ 1763 /* ---------------------------------------*/ 1764 1765 static class AllowedProfileExpression extends ACLProfileExpression 1766 { 1767 public AllowedProfileExpression (String ... profileIds) 1768 { 1769 super(__PROPERTY_NAME_ALLOWED_PROFILES, profileIds); 1770 } 1771 } 1772 1773 static class DeniedProfileExpression extends ACLProfileExpression 1774 { 1775 public DeniedProfileExpression (String ... profileIds) 1776 { 1777 super(__PROPERTY_NAME_DENIED_PROFILES, profileIds); 1778 } 1779 } 1780 1781 static class AnyConnectedDeniedProfileExpression extends ACLProfileExpression 1782 { 1783 public AnyConnectedDeniedProfileExpression (String ... profileIds) 1784 { 1785 super(__PROPERTY_NAME_DENIED_ANY_CONNECTED_PROFILES, profileIds); 1786 } 1787 } 1788 1789 static class AnyConnectedAllowedProfileExpression extends ACLProfileExpression 1790 { 1791 public AnyConnectedAllowedProfileExpression (String ... profileIds) 1792 { 1793 super(__PROPERTY_NAME_ALLOWED_ANY_CONNECTED_PROFILES, profileIds); 1794 } 1795 } 1796 1797 static class AnonymousDeniedProfileExpression extends ACLProfileExpression 1798 { 1799 public AnonymousDeniedProfileExpression (String ... profileIds) 1800 { 1801 super(__PROPERTY_NAME_DENIED_ANONYMOUS_PROFILES, profileIds); 1802 } 1803 } 1804 1805 static class AnonymousAllowedProfileExpression extends ACLProfileExpression 1806 { 1807 public AnonymousAllowedProfileExpression (String ... profileIds) 1808 { 1809 super(__PROPERTY_NAME_ALLOWED_ANONYMOUS_PROFILES, profileIds); 1810 } 1811 } 1812 1813 static class ACLProfileExpression implements Expression 1814 { 1815 private String[] _profileIds; 1816 private String _propertyName; 1817 1818 public ACLProfileExpression (String propertyName, String ... profileIds) 1819 { 1820 _propertyName = propertyName; 1821 _profileIds = profileIds; 1822 } 1823 1824 @Override 1825 public String build() 1826 { 1827 boolean isFirst = true; 1828 StringBuilder sb = new StringBuilder("("); 1829 1830 for (String profileId : _profileIds) 1831 { 1832 if (isFirst) 1833 { 1834 isFirst = false; 1835 } 1836 else 1837 { 1838 sb.append(" or "); 1839 } 1840 1841 sb.append("@") 1842 .append(_propertyName) 1843 .append(Operator.EQ) 1844 .append("'").append(profileId).append("'"); 1845 } 1846 1847 if (isFirst) 1848 { 1849 return ""; 1850 } 1851 else 1852 { 1853 return sb.append(")").toString(); 1854 } 1855 } 1856 } 1857}