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