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.core.ui.right; 017 018import java.util.ArrayList; 019import java.util.HashMap; 020import java.util.LinkedHashMap; 021import java.util.List; 022import java.util.Map; 023import java.util.Map.Entry; 024import java.util.Optional; 025import java.util.Set; 026import java.util.stream.Collectors; 027 028import org.apache.avalon.framework.parameters.Parameters; 029import org.apache.avalon.framework.service.ServiceException; 030import org.apache.avalon.framework.service.ServiceManager; 031import org.apache.cocoon.acting.ServiceableAction; 032import org.apache.cocoon.environment.ObjectModelHelper; 033import org.apache.cocoon.environment.Redirector; 034import org.apache.cocoon.environment.Request; 035import org.apache.cocoon.environment.SourceResolver; 036 037import org.ametys.core.cocoon.JSonReader; 038import org.ametys.core.group.Group; 039import org.ametys.core.group.GroupDirectoryDAO; 040import org.ametys.core.group.GroupIdentity; 041import org.ametys.core.group.GroupManager; 042import org.ametys.core.right.ProfileAssignmentStorage.AnonymousOrAnyConnectedKeys; 043import org.ametys.core.right.ProfileAssignmentStorage.UserOrGroup; 044import org.ametys.core.right.ProfileAssignmentStorageExtensionPoint; 045import org.ametys.core.right.RightAssignmentContext; 046import org.ametys.core.right.RightAssignmentContextExtensionPoint; 047import org.ametys.core.right.RightProfilesDAO; 048import org.ametys.core.ui.right.ProfileAssignmentsToolClientSideElement.AccessType; 049import org.ametys.core.ui.right.ProfileAssignmentsToolClientSideElement.TargetType; 050import org.ametys.core.user.User; 051import org.ametys.core.user.UserIdentity; 052import org.ametys.core.user.UserManager; 053import org.ametys.core.user.population.UserPopulationDAO; 054 055/** 056 * Action for generating the grid for profile assignments 057 */ 058public class GetProfileAssignmentsAction extends ServiceableAction 059{ 060 /** The profile assignment storage component */ 061 protected ProfileAssignmentStorageExtensionPoint _profileAssignmentStorageEP; 062 /** The extension point for right assignment contexts */ 063 protected RightAssignmentContextExtensionPoint _rightAssignmentContextEP; 064 /** The profiles DAO */ 065 protected RightProfilesDAO _profilesDAO; 066 /** The DAO for user populations */ 067 protected UserPopulationDAO _userPopulationDAO; 068 /** The user manager */ 069 protected UserManager _userManager; 070 /** The DAO for group directories */ 071 protected GroupDirectoryDAO _groupDirectoryDAO; 072 /** The group manager */ 073 protected GroupManager _groupManager; 074 075 @Override 076 public void service(ServiceManager smanager) throws ServiceException 077 { 078 super.service(smanager); 079 _profileAssignmentStorageEP = (ProfileAssignmentStorageExtensionPoint) smanager.lookup(ProfileAssignmentStorageExtensionPoint.ROLE); 080 _rightAssignmentContextEP = (RightAssignmentContextExtensionPoint) smanager.lookup(RightAssignmentContextExtensionPoint.ROLE); 081 _userPopulationDAO = (UserPopulationDAO) smanager.lookup(UserPopulationDAO.ROLE); 082 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 083 _groupDirectoryDAO = (GroupDirectoryDAO) smanager.lookup(GroupDirectoryDAO.ROLE); 084 _groupManager = (GroupManager) smanager.lookup(GroupManager.ROLE); 085 } 086 087 @SuppressWarnings("unchecked") 088 @Override 089 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 090 { 091 if (_profilesDAO == null) 092 { 093 _profilesDAO = (RightProfilesDAO) manager.lookup(RightProfilesDAO.ROLE); 094 } 095 096 Map<String, Object> result = new HashMap<>(); 097 Request request = ObjectModelHelper.getRequest(objectModel); 098 099 Map jsParameters = (Map<String, Object>) objectModel.get(ObjectModelHelper.PARENT_CONTEXT); 100 101 String rightAssignmentCtxId = (String) jsParameters.get("rightAssignmentContextId"); 102 RightAssignmentContext rightCtx = _rightAssignmentContextEP.getExtension(rightAssignmentCtxId); 103 104 Object jsContext = jsParameters.get("context"); 105 Object context = rightCtx.convertJSContext(jsContext); 106 107 List<String> profileIds = (List<String>) jsParameters.get("profileIds"); 108 if (profileIds == null) 109 { 110 // Get the identifiers of all existing profiles 111 profileIds = _profilesDAO.getProfiles().stream().map(profile -> profile.getId()).collect(Collectors.toList()); 112 } 113 114 List<Map<String, Object>> assignments = new ArrayList<>(); 115 116 assignments.add(_getAssignmentForAnonymous(rightCtx, context, profileIds)); 117 assignments.add(_getAssignmentForAnyConnectedUser(rightCtx, context, profileIds)); 118 assignments.addAll(_getAssignmentForUsers(rightCtx, context, context, profileIds).values()); 119 assignments.addAll(_getAssignmentForGroups(rightCtx, context, context, profileIds).values()); 120 121 result.put("assignments", assignments); 122 123 request.setAttribute(JSonReader.OBJECT_TO_READ, result); 124 125 return EMPTY_MAP; 126 } 127 128 private Map<String, Object> _getAssignmentForAnonymous(RightAssignmentContext rightCtx, Object context, List<String> profileIds) 129 { 130 Map<String, Object> assignment = new HashMap<>(); 131 132 assignment.put("targetType", TargetType.ANONYMOUS.toString()); 133 134 for (String profileId : profileIds) 135 { 136 _getAssignmentForAnonymous(rightCtx, assignment, context, context, profileId); 137 } 138 139 return assignment; 140 } 141 142 private void _getAssignmentForAnonymous(RightAssignmentContext rightCtx, Map<String, Object> assignment, Object initialContext, Object currentContext, String profileId) 143 { 144 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousAndAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(currentContext); 145 146 Set<String> deniedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_DENIED)).orElse(Set.of()); 147 if (deniedProfiles.contains(profileId)) 148 { 149 assignment.put(profileId, currentContext == initialContext ? AccessType.DENY.toString() : AccessType.INHERITED_DENY.toString()); 150 return; 151 } 152 153 Set<String> allowedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANONYMOUS_ALLOWED)).orElse(Set.of()); 154 if (allowedProfiles.contains(profileId)) 155 { 156 assignment.put(profileId, currentContext == initialContext ? AccessType.ALLOW.toString() : AccessType.INHERITED_ALLOW.toString()); 157 return; 158 } 159 160 if (!_profileAssignmentStorageEP.isInheritanceDisallowed(currentContext)) 161 { 162 // Can not determine assignment on current context, up to parent context 163 Set<Object> parentContexts = rightCtx.getParentContexts(currentContext); 164 if (parentContexts != null) 165 { 166 for (Object parentContext : parentContexts) 167 { 168 Map<String, Object> parentAssignment = new HashMap<>(); 169 _getAssignmentForAnonymous(rightCtx, parentAssignment, initialContext, parentContext, profileId); 170 171 String parentValue = (String) parentAssignment.get(profileId); 172 173 if (AccessType.INHERITED_DENY.toString().equals(parentValue)) 174 { 175 assignment.put(profileId, AccessType.INHERITED_DENY.toString()); 176 return; 177 } 178 else if (AccessType.INHERITED_ALLOW.toString().equals(parentValue)) 179 { 180 assignment.put(profileId, AccessType.INHERITED_ALLOW.toString()); 181 } 182 } 183 } 184 } 185 } 186 187 private Map<String, Object> _getAssignmentForAnyConnectedUser(RightAssignmentContext rightCtx, Object context, List<String> profileIds) 188 { 189 Map<String, Object> assignment = new HashMap<>(); 190 191 assignment.put("targetType", TargetType.ANYCONNECTED_USER.toString()); 192 193 for (String profileId : profileIds) 194 { 195 _getAssignmentForAnyConnectedUser(rightCtx, assignment, context, context, profileId); 196 } 197 198 return assignment; 199 } 200 201 private void _getAssignmentForAnyConnectedUser(RightAssignmentContext rightCtx, Map<String, Object> assignment, Object initialContext, Object currentContext, String profileId) 202 { 203 Map<AnonymousOrAnyConnectedKeys, Set<String>> profilesForAnonymousAndAnyConnectedUser = _profileAssignmentStorageEP.getProfilesForAnonymousAndAnyConnectedUser(currentContext); 204 205 Set<String> deniedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_DENIED)).orElse(Set.of()); 206 if (deniedProfiles.contains(profileId)) 207 { 208 assignment.put(profileId, currentContext == initialContext ? AccessType.DENY.toString() : AccessType.INHERITED_DENY.toString()); 209 return; 210 } 211 212 Set<String> allowedProfiles = Optional.ofNullable(profilesForAnonymousAndAnyConnectedUser.get(AnonymousOrAnyConnectedKeys.ANYCONNECTEDUSER_ALLOWED)).orElse(Set.of()); 213 if (allowedProfiles.contains(profileId)) 214 { 215 assignment.put(profileId, currentContext == initialContext ? AccessType.ALLOW.toString() : AccessType.INHERITED_ALLOW.toString()); 216 return; 217 } 218 219 if (!_profileAssignmentStorageEP.isInheritanceDisallowed(currentContext)) 220 { 221 // Can not determines assignment on current context, up to parent context 222 Set<Object> parentContexts = rightCtx.getParentContexts(currentContext); 223 if (parentContexts != null) 224 { 225 for (Object parentContext : parentContexts) 226 { 227 Map<String, Object> parentAssignment = new HashMap<>(); 228 _getAssignmentForAnyConnectedUser(rightCtx, parentAssignment, initialContext, parentContext, profileId); 229 230 String parentValue = (String) parentAssignment.get(profileId); 231 232 if (AccessType.INHERITED_DENY.toString().equals(parentValue)) 233 { 234 assignment.put(profileId, AccessType.INHERITED_DENY.toString()); 235 return; 236 } 237 else if (AccessType.INHERITED_ALLOW.toString().equals(parentValue)) 238 { 239 assignment.put(profileId, AccessType.INHERITED_ALLOW.toString()); 240 } 241 } 242 } 243 } 244 } 245 246 private Map<UserIdentity, Map<String, Object>> _getAssignmentForUsers(RightAssignmentContext rightCtx, Object initialContext, Object context, List<String> profileIds) 247 { 248 Map<UserIdentity, Map<String, Object>> assignments = new LinkedHashMap<>(); 249 250 // Get all user with a denied profile on current context 251 Map<UserIdentity, Map<UserOrGroup, Set<String>>> profilesForUsers = _profileAssignmentStorageEP.getProfilesForUsers(context, null); 252 for (Entry<UserIdentity, Map<UserOrGroup, Set<String>>> entry : profilesForUsers.entrySet()) 253 { 254 _getAssignementForDeniedUser(initialContext, profileIds, assignments, context, Optional.ofNullable(entry.getValue().get(UserOrGroup.DENIED)).orElse(Set.of()), entry.getKey()); 255 } 256 257 // Get all user with a allowed profile on current context 258 for (Entry<UserIdentity, Map<UserOrGroup, Set<String>>> entry : profilesForUsers.entrySet()) 259 { 260 _getAssignementForAllowedUser(initialContext, profileIds, assignments, context, Optional.ofNullable(entry.getValue().get(UserOrGroup.ALLOWED)).orElse(Set.of()), entry.getKey()); 261 } 262 263 if (!_profileAssignmentStorageEP.isInheritanceDisallowed(context)) 264 { 265 // Up to parent context 266 Set<Object> parentContexts = rightCtx.getParentContexts(context); 267 if (parentContexts != null) 268 { 269 Map<UserIdentity, Map<String, Object>> allParentsAssignments = new HashMap<>(); 270 for (Object parentContext : parentContexts) 271 { 272 Map<UserIdentity, Map<String, Object>> parentAssignment = _getAssignmentForUsers(rightCtx, initialContext, parentContext, profileIds); 273 _mergeUser(allParentsAssignments, parentAssignment, false); 274 } 275 276 _mergeUser(assignments, allParentsAssignments, true); 277 } 278 } 279 280 return assignments; 281 } 282 283 private void _getAssignementForAllowedUser(Object context, List<String> profileIds, Map<UserIdentity, Map<String, Object>> assignments, Object currentContext, 284 Set<String> allowedProfilesForUser, UserIdentity userIdentity) 285 { 286 // Check if the user still exits 287 User user = _userManager.getUser(userIdentity); 288 if (user != null) 289 { 290 if (!assignments.containsKey(userIdentity)) 291 { 292 assignments.put(userIdentity, _user2json(user)); 293 } 294 295 Map<String, Object> userAssignment = assignments.get(userIdentity); 296 297 for (String profileId : allowedProfilesForUser) 298 { 299 if (profileIds.contains(profileId) && !userAssignment.containsKey(profileId)) 300 { 301 userAssignment.put(profileId, currentContext == context ? AccessType.ALLOW.toString() : AccessType.INHERITED_ALLOW.toString()); 302 } 303 } 304 } 305 } 306 307 private void _getAssignementForDeniedUser(Object context, List<String> profileIds, Map<UserIdentity, Map<String, Object>> assignments, Object currentContext, 308 Set<String> deniedProfilesForUser, UserIdentity userIdentity) 309 { 310 // Check if the user still exits 311 User user = _userManager.getUser(userIdentity); 312 if (user != null) 313 { 314 if (!assignments.containsKey(userIdentity)) 315 { 316 Map<String, Object> user2json = _user2json(user); 317 if (user2json != null) 318 { 319 assignments.put(userIdentity, user2json); 320 } 321 } 322 323 Map<String, Object> userAssignment = assignments.get(userIdentity); 324 325 for (String profileId : deniedProfilesForUser) 326 { 327 if (profileIds.contains(profileId) && !userAssignment.containsKey(profileId)) 328 { 329 userAssignment.put(profileId, currentContext == context ? AccessType.DENY.toString() : AccessType.INHERITED_DENY.toString()); 330 } 331 } 332 } 333 } 334 335 private Map<GroupIdentity, Map<String, Object>> _getAssignmentForGroups(RightAssignmentContext rightCtx, Object initialContext, Object context, List<String> profileIds) 336 { 337 Map<GroupIdentity, Map<String, Object>> assignments = new LinkedHashMap<>(); 338 339 // Get all user with a denied profile on current context 340 Map<GroupIdentity, Map<UserOrGroup, Set<String>>> profilesForGroups = _profileAssignmentStorageEP.getProfilesForGroups(context, null); 341 for (Entry<GroupIdentity, Map<UserOrGroup, Set<String>>> entry : profilesForGroups.entrySet()) 342 { 343 _getAssignmentForDeniedGroup(initialContext, profileIds, assignments, context, Optional.ofNullable(entry.getValue().get(UserOrGroup.DENIED)).orElse(Set.of()), entry.getKey()); 344 } 345 346 // Get all user with a allowed profile on current context 347 for (Entry<GroupIdentity, Map<UserOrGroup, Set<String>>> entry : profilesForGroups.entrySet()) 348 { 349 _getAssignementForAllowedGroup(initialContext, profileIds, assignments, context, Optional.ofNullable(entry.getValue().get(UserOrGroup.ALLOWED)).orElse(Set.of()), entry.getKey()); 350 } 351 352 if (!_profileAssignmentStorageEP.isInheritanceDisallowed(context)) 353 { 354 // Up to parent context 355 Set<Object> parentContexts = rightCtx.getParentContexts(context); 356 if (parentContexts != null) 357 { 358 Map<GroupIdentity, Map<String, Object>> allParentsAssignments = new HashMap<>(); 359 for (Object parentContext : parentContexts) 360 { 361 Map<GroupIdentity, Map<String, Object>> parentAssignment = _getAssignmentForGroups(rightCtx, initialContext, parentContext, profileIds); 362 _mergeGroup(allParentsAssignments, parentAssignment, false); 363 } 364 365 _mergeGroup(assignments, allParentsAssignments, true); 366 } 367 } 368 369 return assignments; 370 } 371 372 private void _mergeUser(Map<UserIdentity, Map<String, Object>> finalAssignments, Map<UserIdentity, Map<String, Object>> parentsAssignments, boolean finalListPrevails) 373 { 374 for (UserIdentity identity : parentsAssignments.keySet()) 375 { 376 if (!finalAssignments.containsKey(identity)) 377 { 378 // Was not existing... overwrite 379 finalAssignments.put(identity, parentsAssignments.get(identity)); 380 } 381 else 382 { 383 // Was existing... merge 384 for (String profileId : parentsAssignments.get(identity).keySet()) 385 { 386 Object assignmentsValue = finalAssignments.get(identity).get(profileId); 387 Object allParentsAssignmentsValue = parentsAssignments.get(identity).get(profileId); 388 389 if (assignmentsValue == null 390 || AccessType.UNKNOWN.toString().equals(assignmentsValue) 391 || !finalListPrevails && AccessType.INHERITED_ALLOW.toString().equals(assignmentsValue) && !AccessType.UNKNOWN.toString().equals(allParentsAssignmentsValue)) 392 { 393 finalAssignments.get(identity).put(profileId, allParentsAssignmentsValue); 394 } 395 } 396 } 397 } 398 } 399 private void _mergeGroup(Map<GroupIdentity, Map<String, Object>> finalAssignments, Map<GroupIdentity, Map<String, Object>> parentsAssignments, boolean finalListPrevails) 400 { 401 for (GroupIdentity identity : parentsAssignments.keySet()) 402 { 403 if (!finalAssignments.containsKey(identity)) 404 { 405 // Was not existing... overwrite 406 finalAssignments.put(identity, parentsAssignments.get(identity)); 407 } 408 else 409 { 410 // Was existing... merge 411 for (String profileId : parentsAssignments.get(identity).keySet()) 412 { 413 Object assignmentsValue = finalAssignments.get(identity).get(profileId); 414 Object allParentsAssignmentsValue = parentsAssignments.get(identity).get(profileId); 415 416 if (assignmentsValue == null 417 || AccessType.UNKNOWN.toString().equals(assignmentsValue) 418 || !finalListPrevails && AccessType.INHERITED_ALLOW.toString().equals(assignmentsValue) && !AccessType.UNKNOWN.toString().equals(allParentsAssignmentsValue)) 419 { 420 finalAssignments.get(identity).put(profileId, allParentsAssignmentsValue); 421 } 422 } 423 } 424 } 425 } 426 427 private void _getAssignementForAllowedGroup(Object context, List<String> profileIds, Map<GroupIdentity, Map<String, Object>> assignments, Object currentContext, 428 Set<String> allowedProfilesForGroup, GroupIdentity gpIdentity) 429 { 430 Group group = _groupManager.getGroup(gpIdentity.getDirectoryId(), gpIdentity.getId()); 431 if (group != null) 432 { 433 if (!assignments.containsKey(gpIdentity)) 434 { 435 assignments.put(gpIdentity, _group2json(group)); 436 } 437 438 Map<String, Object> gpAssignment = assignments.get(gpIdentity); 439 440 for (String profileId : allowedProfilesForGroup) 441 { 442 if (profileIds.contains(profileId) && !gpAssignment.containsKey(profileId)) 443 { 444 gpAssignment.put(profileId, currentContext == context ? AccessType.ALLOW.toString() : AccessType.INHERITED_ALLOW.toString()); 445 } 446 } 447 } 448 } 449 450 private void _getAssignmentForDeniedGroup(Object context, List<String> profileIds, Map<GroupIdentity, Map<String, Object>> assignments, Object currentContext, 451 Set<String> deniedProfilesForGroup, GroupIdentity gpIdentity) 452 { 453 Group group = _groupManager.getGroup(gpIdentity.getDirectoryId(), gpIdentity.getId()); 454 if (group != null) 455 { 456 if (!assignments.containsKey(gpIdentity)) 457 { 458 assignments.put(gpIdentity, _group2json(group)); 459 } 460 461 Map<String, Object> gpAssignment = assignments.get(gpIdentity); 462 463 for (String profileId : deniedProfilesForGroup) 464 { 465 if (profileIds.contains(profileId) && !gpAssignment.containsKey(profileId)) 466 { 467 gpAssignment.put(profileId, currentContext == context ? AccessType.DENY.toString() : AccessType.INHERITED_DENY.toString()); 468 } 469 } 470 } 471 } 472 473 private Map<String, Object> _user2json(User user) 474 { 475 Map<String, Object> assignment = new HashMap<>(); 476 assignment.put("targetType", TargetType.USER.toString()); 477 478 String login = user.getIdentity().getLogin(); 479 String populationId = user.getIdentity().getPopulationId(); 480 assignment.put("login", login); 481 assignment.put("populationId", populationId); 482 assignment.put("populationLabel", _userPopulationDAO.getUserPopulation(populationId).getLabel()); 483 assignment.put("groups", _groupManager.getUserGroups(user.getIdentity()).stream() 484 .map(this::_userGroup2json) 485 .collect(Collectors.toList())); 486 assignment.put("userSortableName", user.getSortableName()); 487 488 return assignment; 489 } 490 491 492 private Map<String, Object> _group2json(Group group) 493 { 494 Map<String, Object> assignment = new HashMap<>(); 495 assignment.put("targetType", TargetType.GROUP.toString()); 496 497 String groupId = group.getIdentity().getId(); 498 String directoryId = group.getIdentity().getDirectoryId(); 499 assignment.put("groupId", groupId); 500 assignment.put("groupDirectory", directoryId); 501 assignment.put("groupDirectoryLabel", _groupDirectoryDAO.getGroupDirectory(directoryId).getLabel()); 502 assignment.put("groupLabel", group.getLabel()); 503 504 return assignment; 505 } 506 507 private Map<String, Object> _userGroup2json(GroupIdentity group) 508 { 509 Map<String, Object> result = new HashMap<>(); 510 result.put("groupId", group.getId()); 511 result.put("groupDirectory", group.getDirectoryId()); 512 return result; 513 } 514}