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.core.ui.right; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.HashSet; 021import java.util.List; 022import java.util.Map; 023import java.util.Objects; 024import java.util.Optional; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.configuration.Configuration; 029import org.apache.avalon.framework.configuration.ConfigurationException; 030import org.apache.avalon.framework.service.ServiceException; 031import org.apache.avalon.framework.service.ServiceManager; 032 033import org.ametys.core.ObservationConstants; 034import org.ametys.core.group.GroupDirectoryDAO; 035import org.ametys.core.group.GroupIdentity; 036import org.ametys.core.group.GroupManager; 037import org.ametys.core.observation.Event; 038import org.ametys.core.observation.ObservationManager; 039import org.ametys.core.right.Profile; 040import org.ametys.core.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys; 041import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup; 042import org.ametys.core.right.ProfileAssignmentStorageExtensionPoint; 043import org.ametys.core.right.RightAssignmentContext; 044import org.ametys.core.right.RightAssignmentContextExtensionPoint; 045import org.ametys.core.right.RightManager; 046import org.ametys.core.right.RightManager.RightResult; 047import org.ametys.core.right.RightProfilesDAO; 048import org.ametys.core.right.RightsException; 049import org.ametys.core.ui.Callable; 050import org.ametys.core.ui.ClientSideElement; 051import org.ametys.core.ui.ClientSideElementHelper; 052import org.ametys.core.ui.StaticClientSideElement; 053import org.ametys.core.user.UserIdentity; 054import org.ametys.plugins.core.user.UserHelper; 055 056/** 057 * {@link ClientSideElement} for the tool displaying the profile assignments 058 */ 059public class ProfileAssignmentsToolClientSideElement extends StaticClientSideElement 060{ 061 /** The profile assignment storage component */ 062 protected ProfileAssignmentStorageExtensionPoint _profileAssignmentStorageEP; 063 /** The extension point for right assignment contexts */ 064 protected RightAssignmentContextExtensionPoint _rightAssignmentContextEP; 065 /** The DAO for group directories */ 066 protected GroupDirectoryDAO _groupDirectoryDAO; 067 /** The group manager */ 068 protected GroupManager _groupManager; 069 /** The observation manager */ 070 protected ObservationManager _observationManager; 071 /** The user helper */ 072 protected UserHelper _userHelper; 073 /** The profile DAO */ 074 protected RightProfilesDAO _profileDAO; 075 076 /** The list of right contexts id handle by the tool */ 077 private Set<String> _rightContexts; 078 private boolean _readerProfileOnly; 079 080 /** 081 * Enumeration of all possible access types 082 */ 083 public enum AccessType 084 { 085 /** 086 * Indicates that the access is allowed 087 */ 088 ALLOW 089 { 090 @Override 091 public String toString() 092 { 093 return "allow"; 094 } 095 }, 096 /** 097 * Indicates that the access is denied 098 */ 099 DENY 100 { 101 @Override 102 public String toString() 103 { 104 return "deny"; 105 } 106 }, 107 /** 108 * Indicates that the access is allowed by inheritance 109 */ 110 INHERITED_ALLOW 111 { 112 @Override 113 public String toString() 114 { 115 return "inherited_allow"; 116 } 117 }, 118 /** 119 * Indicates that the access is denied by inheritance 120 */ 121 INHERITED_DENY 122 { 123 @Override 124 public String toString() 125 { 126 return "inherited_deny"; 127 } 128 }, 129 /** 130 * Indicates that the access can not be determined 131 */ 132 UNKNOWN 133 { 134 @Override 135 public String toString() 136 { 137 return "unknown"; 138 } 139 } 140 } 141 142 /** 143 * Enumeration of all possible target types 144 */ 145 public enum TargetType 146 { 147 /** 148 * Indicates that the target is the anonymous user 149 */ 150 ANONYMOUS 151 { 152 @Override 153 public String toString() 154 { 155 return "anonymous"; 156 } 157 }, 158 /** 159 * Indicates that the target is the anonymous user 160 */ 161 ANYCONNECTED_USER 162 { 163 @Override 164 public String toString() 165 { 166 return "anyconnected_user"; 167 } 168 }, 169 /** 170 * Indicates that the target is a user 171 */ 172 USER 173 { 174 @Override 175 public String toString() 176 { 177 return "user"; 178 } 179 }, 180 /** 181 * Indicates that the target is a group 182 */ 183 GROUP 184 { 185 @Override 186 public String toString() 187 { 188 return "group"; 189 } 190 } 191 } 192 193 @Override 194 public void service(ServiceManager smanager) throws ServiceException 195 { 196 super.service(smanager); 197 _profileAssignmentStorageEP = (ProfileAssignmentStorageExtensionPoint) smanager.lookup(ProfileAssignmentStorageExtensionPoint.ROLE); 198 _rightAssignmentContextEP = (RightAssignmentContextExtensionPoint) smanager.lookup(RightAssignmentContextExtensionPoint.ROLE); 199 _groupDirectoryDAO = (GroupDirectoryDAO) smanager.lookup(GroupDirectoryDAO.ROLE); 200 _groupManager = (GroupManager) smanager.lookup(GroupManager.ROLE); 201 _observationManager = (ObservationManager) smanager.lookup(ObservationManager.ROLE); 202 _userHelper = (UserHelper) smanager.lookup(UserHelper.ROLE); 203 _profileDAO = (RightProfilesDAO) smanager.lookup(RightProfilesDAO.ROLE); 204 } 205 206 @Override 207 public void configure(Configuration configuration) throws ConfigurationException 208 { 209 super.configure(configuration); 210 211 _configureRightContextIds(configuration); 212 213 _readerProfileOnly = configuration.getChild("class").getChild("reader-profile-only").getValueAsBoolean(false); 214 } 215 216 /** 217 * Configure the restricted right context ids 218 * @param configuration the global configuration 219 * @throws ConfigurationException The configuration is incorrect 220 */ 221 protected void _configureRightContextIds(Configuration configuration) throws ConfigurationException 222 { 223 _rightContexts = new HashSet<>(); 224 225 Configuration[] rightCtxConfig = configuration.getChild("class").getChild("right-contexts").getChildren("right-context"); 226 227 for (Configuration conf : rightCtxConfig) 228 { 229 _rightContexts.add(conf.getValue()); 230 } 231 } 232 233 /** 234 * Get the right assignments contexts handled by this tool 235 * @return the right assignments contexts 236 */ 237 protected Set<RightAssignmentContext> getRightAssignmentContexts() 238 { 239 if (!_rightContexts.isEmpty()) 240 { 241 return _rightContexts 242 .stream() 243 .map(id -> _rightAssignmentContextEP.getExtension(id)) 244 .filter(Objects::nonNull) 245 .collect(Collectors.toSet()); 246 } 247 else 248 { 249 // No restriction on handle contexts, get all contexts except private contexts 250 return _rightAssignmentContextEP.getExtensionsIds() 251 .stream() 252 .map(id -> _rightAssignmentContextEP.getExtension(id)) 253 .filter(ctx -> !ctx.isPrivate()) 254 .collect(Collectors.toSet()); 255 } 256 } 257 258 @Override 259 public List<Script> getScripts(boolean ignoreRights, Map<String, Object> contextParameters) 260 { 261 List<Script> scripts = super.getScripts(ignoreRights, contextParameters); 262 263 if (scripts.size() > 0) 264 { 265 Script script = ClientSideElementHelper.cloneScript(scripts.get(0)); 266 267 Map<String, Object> jsClasses = new HashMap<>(); 268 script.getParameters().put("classes", jsClasses); 269 270 Set<RightAssignmentContext> rightAssignmentContexts = getRightAssignmentContexts(); 271 for (RightAssignmentContext rightAssignmentContext : rightAssignmentContexts) 272 { 273 List<Script> rightAssignmentContextScripts = rightAssignmentContext.getScripts(ignoreRights, contextParameters); 274 int index = 0; 275 for (Script rightAssignmentContextScript: rightAssignmentContextScripts) 276 { 277 Map<String, Object> classInfo = new HashMap<>(); 278 classInfo.put("className", rightAssignmentContextScript.getScriptClassname()); 279 classInfo.put("serverId", rightAssignmentContext.getId()); 280 classInfo.put("parameters", rightAssignmentContextScript.getParameters()); 281 jsClasses.put(rightAssignmentContext.getId() + "-" + index++, classInfo); 282 283 script.getScriptFiles().addAll(rightAssignmentContextScript.getScriptFiles()); 284 script.getCSSFiles().addAll(rightAssignmentContextScript.getCSSFiles()); 285 } 286 } 287 288 scripts = new ArrayList<>(); 289 scripts.add(script); 290 } 291 292 return scripts; 293 } 294 295 /** 296 * Gets the groups of a user as JSON 297 * @param login The login of the user 298 * @param populationId The population of the user 299 * @return the groups of a user as JSON 300 */ 301 @Callable 302 public List<Map<String, Object>> getUserGroups(String login, String populationId) 303 { 304 return _groupManager.getUserGroups(new UserIdentity(login, populationId)).stream() 305 .map(this::_groupToJson) 306 .collect(Collectors.toList()); 307 } 308 309 private Map<String, Object> _groupToJson(GroupIdentity groupIdentity) 310 { 311 Map<String, Object> result = new HashMap<>(); 312 result.put("groupId", groupIdentity.getId()); 313 result.put("groupDirectory", groupIdentity.getDirectoryId()); 314 return result; 315 } 316 317 /** 318 * Save some changes made client-side. 319 * @param rightAssignmentCtxId The id of the right assignment context 320 * @param jsContext The JS object context 321 * @param assignmentsInfo The list of all the changes to make. Each map in the list must contain the following keys: 322 * <ol> 323 * <li><b>profileId</b> for the id of the profile (as a string)</li> 324 * <li><b>assignment</b> for the kind of assignment (can be ACCESS_TYPE_ALLOW, ACCESS_TYPE_DENY...)</li> 325 * <li><b>assignmentType</b> expects one of these four strings: "user", "group", "anonymous", "anyConnectedUser"</li> 326 * <li><b>identity</b> Can be null if assignmentType is "anonymous" or "anyConnectedUser". If "user", must be a map with the keys "login" and "populationId". If "group", must be a map with the keys "groupId" and "groupDirectory"</li> 327 * </ol> 328 * @return a map containing 3 objects : 329 * success : boolean, everything is saved 330 * successInfos : elements from assignmentsInfo that are saved 331 * errorInfos : elements from assignmentsInfo that are not saved 332 */ 333 @SuppressWarnings("unchecked") 334 @Callable 335 public Map<String, Object> saveChanges(String rightAssignmentCtxId, Object jsContext, List<Map<String, Object>> assignmentsInfo) 336 { 337 Map<String, Object> result = new HashMap<>(); 338 List<Map<String, Object>> successInfos = new ArrayList<>(); 339 List<Map<String, Object>> errorInfos = new ArrayList<>(); 340 341 UserIdentity user = _currentUserProvider.getUser(); 342 Set<GroupIdentity> groups = _groupManager.getUserGroups(user); 343 344 if (!_checkRightAssignmentContext(rightAssignmentCtxId)) 345 { 346 throw new RightsException("The user '" + user + "' try to assign profile on unauthorized context '" + rightAssignmentCtxId + "'"); 347 } 348 349 Map<String, String> rights = getRights(Map.of()); 350 // Remove delegation rights because it is a specific right, not sufficient to allow right assignment 351 rights.remove("CMS_Rights_Delegate_Rights"); 352 353 RightAssignmentContext rightAssignmentContext = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 354 Object context = rightAssignmentContext.convertJSContext(jsContext); 355 356 boolean hasHandleRight = hasRight(rights, context); 357 358 Set<String> updatedProfiles = new HashSet<>(); 359 360 String contextIdentifier = rightAssignmentContext.getContextIdentifier(context); 361 for (Map<String, Object> assignmentInfo : assignmentsInfo) 362 { 363 String profileId = (String) assignmentInfo.get("profileId"); 364 365 if (_readerProfileOnly && !RightManager.READER_PROFILE_ID.equals(profileId)) 366 { 367 throw new RightsException("The user '" + user + "' try to the assign profile '" + profileId + "' on the object context '" + jsContext + "' but only the reader profile is allowed for the right assignment context '" + rightAssignmentCtxId + "'"); 368 } 369 370 String assignment = (String) assignmentInfo.get("assignment"); 371 String targetType = (String) assignmentInfo.get("targetType"); 372 373 Profile profile = _profileDAO.getProfile(profileId); 374 assignmentInfo.put("profileLabel", profile.getLabel()); 375 376 if (hasHandleRight || canDelegateRights(user, groups, profileId, assignment, context)) 377 { 378 updatedProfiles.add(profileId); 379 Map<String, String> identity = (Map<String, String>) assignmentInfo.get("identity"); 380 _saveChange(context, profileId, assignment, targetType, identity); 381 successInfos.add(assignmentInfo); 382 } 383 else 384 { 385 errorInfos.add(assignmentInfo); 386 } 387 } 388 _notifyObservers(context, contextIdentifier, updatedProfiles); 389 390 result.put("successInfos", successInfos); 391 result.put("errorInfos", errorInfos); 392 result.put("success", errorInfos.isEmpty()); 393 394 return result; 395 } 396 397 /** 398 * Determine following the right parameter if the user has right to access this feature 399 * 400 * @param rights The rights (name, context) to check. Can be empty. 401 * @param context The object context 402 * @return true if the user has the right or if there is not right and false otherwise 403 */ 404 protected boolean hasRight(Map<String, String> rights, Object context) 405 { 406 return hasRight(rights); 407 } 408 409 /** 410 * Returns true if right assignment context is part of handled right assignment contexts 411 * @param rightAssignmentCtxId the id of right assignment context 412 * @return true if it right assignment context is allowed 413 */ 414 protected boolean _checkRightAssignmentContext(String rightAssignmentCtxId) 415 { 416 Set<String> rightAssignmentCtxIds = getRightAssignmentContexts().stream().map(RightAssignmentContext::getId).collect(Collectors.toSet()); 417 return rightAssignmentCtxIds.contains(rightAssignmentCtxId); 418 } 419 420 /** 421 * Apply assignments and inheritance status on given contexts. The existing assignments will be reset for all targets 422 * @param rightAssignmentCtxId The id of the right assignment context 423 * @param targetContexts The JS object contexts with their inheritance enable status 424 * @param assignmentsInfo The list of all the new assignments. Each map in the list must contain the following keys: 425 * <ol> 426 * <li><b>profileId</b> for the id of the profile (as a string)</li> 427 * <li><b>assignment</b> for the kind of assignment (can be ACCESS_TYPE_ALLOW, ACCESS_TYPE_DENY...)</li> 428 * <li><b>assignmentType</b> expects one of these four strings: "user", "group", "anonymous", "anyConnectedUser"</li> 429 * <li><b>identity</b> Can be null if assignmentType is "anonymous" or "anyConnectedUser". If "user", must be a map with the keys "login" and "populationId". If "group", must be a map with the keys "groupId" and "groupDirectory"</li> 430 * </ol> 431 * @param disallowInheritance true to disallow the inheritance, false to allow. 432 * @return true if assignments were correctly applied 433 */ 434 @SuppressWarnings("unchecked") 435 @Callable 436 public boolean applyAssignments(String rightAssignmentCtxId, List<Map<String, Object>> targetContexts, List<Map<String, Object>> assignmentsInfo, boolean disallowInheritance) 437 { 438 UserIdentity user = _currentUserProvider.getUser(); 439 if (!hasRight(getRights(Map.of()))) 440 { 441 getLogger().error("The user '" + user + "' try to apply assignments without sufficient rights"); 442 return false; 443 } 444 445 if (!_checkRightAssignmentContext(rightAssignmentCtxId)) 446 { 447 throw new RightsException("The user '" + user + "' tries to apply assignments on an unauthorized context '" + rightAssignmentCtxId + "'"); 448 } 449 450 Set<String> allProfileIds = _profileDAO.getProfiles().stream() 451 .map(Profile::getId) 452 .collect(Collectors.toSet()); 453 454 // Compute the targets targeted by the new assignments 455 Set<AssignmentTarget> assignmentTargets = _getAssignmentTargets(assignmentsInfo); 456 457 RightAssignmentContext rightAssignmentContext = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 458 459 for (Map<String, Object> targetContext : targetContexts) 460 { 461 String jsContext = (String) targetContext.get("context"); 462 463 Object context = rightAssignmentContext.convertJSContext(jsContext); 464 465 // First reset existings assignments for each targets 466 for (AssignmentTarget assignmentTarget : assignmentTargets) 467 { 468 _resetAssignments(allProfileIds, context, assignmentTarget.targetType(), assignmentTarget.identity()); 469 } 470 471 // Then apply new assignments 472 for (Map<String, Object> assignmentInfo : assignmentsInfo) 473 { 474 String profileId = (String) assignmentInfo.get("profileId"); 475 if (_readerProfileOnly && !RightManager.READER_PROFILE_ID.equals(profileId)) 476 { 477 throw new RightsException("The user '" + user + "' try to apply the profile '" + profileId + "' on the object context '" + jsContext + "' but only the reader profile is allowed for the right assignment context '" + rightAssignmentCtxId + "'"); 478 } 479 String targetType = (String) assignmentInfo.get("targetType"); 480 Map<String, String> identity = (Map<String, String>) assignmentInfo.get("identity"); 481 482 // Apply new assignments 483 String assignment = (String) assignmentInfo.get("assignment"); 484 _saveChange(context, profileId, assignment, targetType, identity); 485 } 486 487 // Apply inheritance (if available) 488 boolean inheritanceAvailable = (boolean) targetContext.get("inheritanceAvailable"); 489 if (inheritanceAvailable) 490 { 491 _profileAssignmentStorageEP.disallowInheritance(context, disallowInheritance); 492 } 493 494 // Notify observers with all profiles 495 String contextIdentifier = rightAssignmentContext.getContextIdentifier(context); 496 _notifyObservers(context, contextIdentifier, allProfileIds); 497 } 498 499 return true; 500 } 501 502 @SuppressWarnings("unchecked") 503 private Set<AssignmentTarget> _getAssignmentTargets(List<Map<String, Object>> assignmentsInfo) 504 { 505 Set<AssignmentTarget> targets = new HashSet<>(); 506 for (Map<String, Object> assignmentInfo : assignmentsInfo) 507 { 508 String targetType = (String) assignmentInfo.get("targetType"); 509 switch (TargetType.valueOf(targetType.toUpperCase())) 510 { 511 case ANONYMOUS: 512 case ANYCONNECTED_USER: 513 targets.add(new AssignmentTarget(targetType, null)); 514 break; 515 case USER: 516 case GROUP: 517 Map<String, String> identity = (Map<String, String>) assignmentInfo.get("identity"); 518 targets.add(new AssignmentTarget(targetType, identity)); 519 break; 520 default: 521 break; 522 } 523 } 524 525 return targets; 526 } 527 528 record AssignmentTarget(String targetType, Map<String, String> identity) { /* empty */ } 529 530 /** 531 * Only allow user with right CMS_Rights_Delegate_Rights to add a profil that this user already have on this context 532 * @param user user that want to de an assignment 533 * @param groups groups of the user 534 * @param profileId profil impacted 535 * @param assignment assignment see {@link AccessType} 536 * @param context context of the assignment 537 * @return <code>true</code> if user can de this assignment 538 */ 539 protected boolean canDelegateRights(UserIdentity user, Set<GroupIdentity> groups, String profileId, String assignment , Object context) 540 { 541 AccessType accessType = assignment != null ? AccessType.valueOf(assignment.toUpperCase()) : AccessType.UNKNOWN; 542 return accessType == AccessType.ALLOW 543 && _rightManager.hasRight(user, "CMS_Rights_Delegate_Rights", "/${WorkspaceName}") == RightResult.RIGHT_ALLOW 544 && _profileAssignmentStorageEP.getPermissions(user, groups, Set.of(profileId), context).get(profileId).toRightResult() == RightResult.RIGHT_ALLOW; 545 } 546 547 /** 548 * Notify observers after modifying profile assignments. 549 * @param context The context 550 * @param contextIdentifier The context identifier 551 * @param profileIds The profiles 552 */ 553 protected void _notifyObservers(Object context, String contextIdentifier, Set<String> profileIds) 554 { 555 _observationManager.notify(new Event(ObservationConstants.EVENT_ACL_UPDATED, _currentUserProvider.getUser(), _getEventParams(context, contextIdentifier, profileIds))); 556 } 557 558 /** 559 * Get the event params for notification. 560 * @param context The context 561 * @param contextIdentifier The context identifier 562 * @param profileIds The profiles 563 * @return the event params 564 */ 565 protected Map<String, Object> _getEventParams(Object context, String contextIdentifier, Set<String> profileIds) 566 { 567 Map<String, Object> eventParams = new HashMap<>(); 568 eventParams.put(ObservationConstants.ARGS_ACL_CONTEXT, context); 569 eventParams.put(ObservationConstants.ARGS_ACL_CONTEXT_IDENTIFIER, contextIdentifier); 570 eventParams.put(ObservationConstants.ARGS_ACL_PROFILES, profileIds); 571 return eventParams; 572 } 573 574 /** 575 * Determines if the inheritance of assignments is disallowed on the given context 576 * @param rightAssignmentCtxId The id of the right assignment context 577 * @param jsContext The JS object context 578 * @return <code>true</code> if the inheritance is disallowed. 579 */ 580 @Callable 581 public boolean isInheritanceDisallowed(String rightAssignmentCtxId, Object jsContext) 582 { 583 RightAssignmentContext rightCtx = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 584 Object context = rightCtx.convertJSContext(jsContext); 585 586 return _profileAssignmentStorageEP.isInheritanceDisallowed(context); 587 } 588 589 /** 590 * Allow or disallow the inheritance of assignments on the given context 591 * @param rightAssignmentCtxId The id of the right assignment context 592 * @param jsContext The JS object context 593 * @param disallow true to disallow the inheritance, false to allow. 594 */ 595 @Callable 596 public void disallowInheritance(String rightAssignmentCtxId, Object jsContext, boolean disallow) 597 { 598 RightAssignmentContext rightCtx = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 599 Object context = rightCtx.convertJSContext(jsContext); 600 String contextIdentifier = rightCtx.getContextIdentifier(context); 601 602 _profileAssignmentStorageEP.disallowInheritance(context, disallow); 603 604 // notify observers for all profiles 605 Set<String> profileIds = _profileDAO.getProfiles().stream() 606 .map(Profile::getId) 607 .collect(Collectors.toSet()); 608 609 _notifyObservers(context, contextIdentifier, profileIds); 610 } 611 612 /** 613 * Get the first permission given by inheritance for a object context and profiles 614 * @param rightAssignmentCtxId The id of the right assignment context 615 * @param jsContext The JS object context 616 * @param profileIds The list of profiles 617 * @param targetType The type of target : anonymous, any connected users, a user or a group 618 * @param identity The identity of the target. Can be null if the target is anonymous or any connected users 619 * @return The first access type given by inheritance for each profile 620 */ 621 @Callable 622 public Map<String, String> getInheritedAssignments (String rightAssignmentCtxId, Object jsContext, List<String> profileIds, String targetType, Map<String, String> identity) 623 { 624 RightAssignmentContext rightCtx = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 625 Object context = rightCtx.convertJSContext(jsContext); 626 627 if (_profileAssignmentStorageEP.isInheritanceDisallowed(context)) 628 { 629 return profileIds.stream() 630 .collect(Collectors.toMap(profileId -> profileId, profileId -> AccessType.UNKNOWN.toString())); 631 } 632 else 633 { 634 return profileIds.stream() 635 .collect(Collectors.toMap(profileId -> profileId, profileId -> getInheritedAssignment(rightAssignmentCtxId, jsContext, profileId, targetType, identity))); 636 } 637 } 638 639 /** 640 * Get the first permission given by inheritance for a object context and a specific profile 641 * @param rightAssignmentCtxId The id of the right assignment context 642 * @param jsContext The JS object context 643 * @param profileId The id of profile 644 * @param targetType The type of target : anonymous, any connected users, a user or a group 645 * @param identity The identity of the target. Can be null if the target is anonymous or any connected users 646 * @return The first access type given by inheritance 647 */ 648 @Callable 649 public String getInheritedAssignment (String rightAssignmentCtxId, Object jsContext, String profileId, String targetType, Map<String, String> identity) 650 { 651 RightAssignmentContext rightCtx = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 652 Object context = rightCtx.convertJSContext(jsContext); 653 654 if (_profileAssignmentStorageEP.isInheritanceDisallowed(context)) 655 { 656 return AccessType.UNKNOWN.toString(); 657 } 658 else 659 { 660 switch (TargetType.valueOf(targetType.toUpperCase())) 661 { 662 case ANONYMOUS: 663 return _getInheritedAssignmentForAnonymous(rightCtx, context, profileId); 664 case ANYCONNECTED_USER: 665 return _getInheritedAssignmentForAnyconnected(rightCtx, context, profileId); 666 case USER: 667 UserIdentity user = _userHelper.json2userIdentity(identity); 668 return _getInheritedAssignmentForUser(rightCtx, context, profileId, user); 669 case GROUP: 670 GroupIdentity group = new GroupIdentity(identity.get("groupId"), identity.get("groupDirectory")); 671 return _getInheritedAssignmentForGroup(rightCtx, context, profileId, group); 672 default: 673 return AccessType.UNKNOWN.toString(); 674 } 675 } 676 } 677 678 private String _getInheritedAssignmentForAnonymous (RightAssignmentContext extension, Object context, String profileId) 679 { 680 String value = AccessType.UNKNOWN.toString(); 681 682 Set<Object> parentContexts = extension.getParentContexts(context); 683 if (parentContexts != null) 684 { 685 for (Object parentContext : parentContexts) 686 { 687 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousAndAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(parentContexts); 688 689 Set<String> deniedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_DENIED)).orElse(Set.of()); 690 if (deniedProfiles.contains(profileId)) 691 { 692 return AccessType.INHERITED_DENY.toString(); 693 } 694 695 Set<String> allowedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_ALLOWED)).orElse(Set.of()); 696 if (allowedProfiles.contains(profileId)) 697 { 698 value = AccessType.INHERITED_ALLOW.toString(); 699 } 700 701 String parentsValue = _getInheritedAssignmentForAnonymous(extension, parentContext, profileId); 702 if (!AccessType.UNKNOWN.toString().equals(parentsValue)) 703 { 704 value = parentsValue; 705 } 706 } 707 } 708 709 return value; 710 } 711 712 private String _getInheritedAssignmentForAnyconnected(RightAssignmentContext extension, Object context, String profileId) 713 { 714 String value = AccessType.UNKNOWN.toString(); 715 716 Set<Object> parentContexts = extension.getParentContexts(context); 717 if (parentContexts != null) 718 { 719 for (Object parentContext : parentContexts) 720 { 721 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousAndAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(parentContexts); 722 723 Set<String> deniedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_DENIED)).orElse(Set.of()); 724 if (deniedProfiles.contains(profileId)) 725 { 726 return AccessType.INHERITED_DENY.toString(); 727 } 728 729 Set<String> allowedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_ALLOWED)).orElse(Set.of()); 730 if (allowedProfiles.contains(profileId)) 731 { 732 value = AccessType.INHERITED_ALLOW.toString(); 733 } 734 735 String parentsValue = _getInheritedAssignmentForAnyconnected(extension, parentContext, profileId); 736 if (!AccessType.UNKNOWN.toString().equals(parentsValue)) 737 { 738 value = parentsValue; 739 } 740 } 741 } 742 743 return value; 744 } 745 746 private String _getInheritedAssignmentForUser(RightAssignmentContext extension, Object context, String profileId, UserIdentity user) 747 { 748 String value = AccessType.UNKNOWN.toString(); 749 750 Set<Object> parentContexts = extension.getParentContexts(context); 751 if (parentContexts != null) 752 { 753 for (Object parentContext : parentContexts) 754 { 755 Map<UserIdentity, Map<UserOrGroup, Set<String>>> profilesForUsers = _profileAssignmentStorageEP.getProfilesForUsers(parentContext, user); 756 757 Set<String> deniedProfiles = Optional.ofNullable(profilesForUsers.get(user)).map(a -> a.get(UserOrGroup.DENIED)).orElse(Set.of()); 758 if (deniedProfiles.contains(profileId)) 759 { 760 return AccessType.INHERITED_DENY.toString(); 761 } 762 763 Set<String> allowedProfiles = Optional.ofNullable(profilesForUsers.get(user)).map(a -> a.get(UserOrGroup.ALLOWED)).orElse(Set.of()); 764 if (allowedProfiles.contains(profileId)) 765 { 766 value = AccessType.INHERITED_ALLOW.toString(); 767 } 768 769 String parentsValue = _getInheritedAssignmentForUser(extension, parentContext, profileId, user); 770 if (!AccessType.UNKNOWN.toString().equals(parentsValue)) 771 { 772 value = parentsValue; 773 } 774 } 775 } 776 777 return value; 778 } 779 780 private String _getInheritedAssignmentForGroup(RightAssignmentContext extension, Object context, String profileId, GroupIdentity group) 781 { 782 String value = AccessType.UNKNOWN.toString(); 783 784 Set<Object> parentContexts = extension.getParentContexts(context); 785 if (parentContexts != null) 786 { 787 for (Object parentContext : parentContexts) 788 { 789 Map<GroupIdentity, Map<UserOrGroup, Set<String>>> profilesForGroups = _profileAssignmentStorageEP.getProfilesForGroups(parentContext, Set.of(group)); 790 791 Set<String> deniedProfiles = Optional.ofNullable(profilesForGroups.get(group)).map(a -> a.get(UserOrGroup.DENIED)).orElse(Set.of()); 792 if (deniedProfiles.contains(profileId)) 793 { 794 return AccessType.INHERITED_DENY.toString(); 795 } 796 797 Set<String> allowedProfiles = Optional.ofNullable(profilesForGroups.get(group)).map(a -> a.get(UserOrGroup.ALLOWED)).orElse(Set.of()); 798 if (allowedProfiles.contains(profileId)) 799 { 800 value = AccessType.INHERITED_ALLOW.toString(); 801 } 802 803 String parentsValue = _getInheritedAssignmentForGroup(extension, parentContext, profileId, group); 804 if (!AccessType.UNKNOWN.toString().equals(parentsValue)) 805 { 806 value = parentsValue; 807 } 808 } 809 } 810 811 return value; 812 } 813 814 private void _resetAssignments(Set<String> profileIds, Object context, String targetType, Map<String, String> identity) 815 { 816 TargetType type = TargetType.valueOf(targetType.toUpperCase()); 817 for (String profileId : profileIds) 818 { 819 switch (type) 820 { 821 case ANONYMOUS: 822 _profileAssignmentStorageEP.removeAllowedProfileFromAnonymous(profileId, context); 823 _profileAssignmentStorageEP.removeDeniedProfileFromAnonymous(profileId, context); 824 break; 825 case ANYCONNECTED_USER: 826 _profileAssignmentStorageEP.removeAllowedProfileFromAnyConnectedUser(profileId, context); 827 _profileAssignmentStorageEP.removeDeniedProfileFromAnyConnectedUser(profileId, context); 828 break; 829 case USER: 830 UserIdentity user = _userHelper.json2userIdentity(identity); 831 _profileAssignmentStorageEP.removeAllowedProfileFromUser(user, profileId, context); 832 _profileAssignmentStorageEP.removeDeniedProfileFromUser(user, profileId, context); 833 break; 834 case GROUP: 835 GroupIdentity group = new GroupIdentity(identity.get("groupId"), identity.get("groupDirectory")); 836 _profileAssignmentStorageEP.removeAllowedProfileFromGroup(group, profileId, context); 837 _profileAssignmentStorageEP.removeDeniedProfileFromGroup(group, profileId, context); 838 break; 839 default: 840 break; 841 } 842 } 843 } 844 845 private void _saveChange(Object context, String profileId, String assignment, String targetType, Map<String, String> identity) 846 { 847 AccessType accessType = assignment != null ? AccessType.valueOf(assignment.toUpperCase()) : AccessType.UNKNOWN; 848 switch (TargetType.valueOf(targetType.toUpperCase())) 849 { 850 case ANONYMOUS: 851 switch (accessType) 852 { 853 case ALLOW: 854 _profileAssignmentStorageEP.removeDeniedProfileFromAnonymous(profileId, context); 855 _profileAssignmentStorageEP.allowProfileToAnonymous(profileId, context); 856 break; 857 case DENY: 858 _profileAssignmentStorageEP.removeAllowedProfileFromAnonymous(profileId, context); 859 _profileAssignmentStorageEP.denyProfileToAnonymous(profileId, context); 860 break; 861 default: 862 _profileAssignmentStorageEP.removeAllowedProfileFromAnonymous(profileId, context); 863 _profileAssignmentStorageEP.removeDeniedProfileFromAnonymous(profileId, context); 864 break; 865 } 866 break; 867 868 case ANYCONNECTED_USER: 869 switch (accessType) 870 { 871 case ALLOW: 872 _profileAssignmentStorageEP.removeDeniedProfileFromAnyConnectedUser(profileId, context); 873 _profileAssignmentStorageEP.allowProfileToAnyConnectedUser(profileId, context); 874 break; 875 case DENY: 876 _profileAssignmentStorageEP.removeAllowedProfileFromAnyConnectedUser(profileId, context); 877 _profileAssignmentStorageEP.denyProfileToAnyConnectedUser(profileId, context); 878 break; 879 default: 880 _profileAssignmentStorageEP.removeAllowedProfileFromAnyConnectedUser(profileId, context); 881 _profileAssignmentStorageEP.removeDeniedProfileFromAnyConnectedUser(profileId, context); 882 break; 883 } 884 break; 885 886 case USER: 887 UserIdentity user = _userHelper.json2userIdentity(identity); 888 switch (accessType) 889 { 890 case ALLOW: 891 _profileAssignmentStorageEP.removeDeniedProfileFromUser(user, profileId, context); 892 _profileAssignmentStorageEP.allowProfileToUser(user, profileId, context); 893 break; 894 case DENY: 895 _profileAssignmentStorageEP.removeAllowedProfileFromUser(user, profileId, context); 896 _profileAssignmentStorageEP.denyProfileToUser(user, profileId, context); 897 break; 898 default: 899 _profileAssignmentStorageEP.removeAllowedProfileFromUser(user, profileId, context); 900 _profileAssignmentStorageEP.removeDeniedProfileFromUser(user, profileId, context); 901 break; 902 } 903 break; 904 905 case GROUP: 906 GroupIdentity group = new GroupIdentity(identity.get("groupId"), identity.get("groupDirectory")); 907 switch (accessType) 908 { 909 case ALLOW: 910 _profileAssignmentStorageEP.removeDeniedProfileFromGroup(group, profileId, context); 911 _profileAssignmentStorageEP.allowProfileToGroup(group, profileId, context); 912 break; 913 case DENY: 914 _profileAssignmentStorageEP.removeAllowedProfileFromGroup(group, profileId, context); 915 _profileAssignmentStorageEP.denyProfileToGroup(group, profileId, context); 916 break; 917 default: 918 _profileAssignmentStorageEP.removeAllowedProfileFromGroup(group, profileId, context); 919 _profileAssignmentStorageEP.removeDeniedProfileFromGroup(group, profileId, context); 920 break; 921 } 922 break; 923 default: 924 break; 925 } 926 } 927 928 929}