use of org.xwiki.security.GroupSecurityReference in project xwiki-platform by xwiki.
the class DefaultSecurityCacheLoader method loadUserGroups.
private Collection<GroupSecurityReference> loadUserGroups(UserSecurityReference user, SecurityReference wiki, Collection<GroupSecurityReference> allGroups, Deque<GroupSecurityReference> branchGroups) throws ParentEntryEvictedException, ConflictingInsertionException, AuthorizationException {
// Retrieve the list of immediate group for the user/group in either the entity wiki or the user/group wiki
Collection<GroupSecurityReference> groups = userBridge.getAllGroupsFor(user, wiki.getOriginalWikiReference());
Collection<GroupSecurityReference> immediateGroup = new ArrayList<GroupSecurityReference>();
// Loads all immediate groups recursively, collecting indirect groups along the way
for (GroupSecurityReference group : groups) {
// Loads the group only if it has never been seen before in the current path to avoid infinite recursion
if (!branchGroups.contains(group)) {
// We check the cache for real nodes (not shadows) since group are coming from their own wiki
Collection<GroupSecurityReference> groupsOfGroup = securityCache.getGroupsFor(group, null);
// And we load the groups only if they are not in the cache
if (groupsOfGroup == null) {
// Add this group into the list of immediate groups for this entry
immediateGroup.add(group);
// Load dependencies recursively
branchGroups.push(group);
loadUserEntry(group, loadUserGroups(group, wiki, allGroups, branchGroups));
branchGroups.pop();
} else {
// Check for possible recursion in the cached groups and add this group only if it is safe
boolean recursionFound = false;
for (GroupSecurityReference existingGroup : groupsOfGroup) {
if (branchGroups.contains(existingGroup)) {
recursionFound = true;
break;
}
}
if (!recursionFound) {
// Add this group into the list of immediate groups for this entry
immediateGroup.add(group);
// Add all group found in the cache for the final result
allGroups.addAll(groupsOfGroup);
}
}
}
}
// Collect groups of this entry for the final result
allGroups.addAll(immediateGroup);
return immediateGroup;
}
use of org.xwiki.security.GroupSecurityReference in project xwiki-platform by xwiki.
the class DefaultSecurityCacheLoader method loadUserEntry.
/**
* Load rules for a user/group into the cache with relations to immediate groups. Groups should be already loaded,
* else a ParentEntryEvictedException will be thrown. The parent chain of the loaded user will be loaded as needed.
*
* @param user The user/group to load.
* @param groups The collection of groups associated with the user/group
* @throws ParentEntryEvictedException if any of the parent entries of the group were evicted.
* @throws ConflictingInsertionException When different threads have inserted conflicting entries into the cache.
* @throws org.xwiki.security.authorization.AuthorizationException on error.
*/
private void loadUserEntry(UserSecurityReference user, Collection<GroupSecurityReference> groups) throws ParentEntryEvictedException, ConflictingInsertionException, AuthorizationException {
// Make sure the parent of the user document is loaded.
Deque<SecurityReference> chain = user.getReversedSecurityReferenceChain();
chain.removeLast();
for (SecurityReference ref : chain) {
SecurityRuleEntry entry = securityCache.get(ref);
if (entry == null) {
entry = securityEntryReader.read(ref);
securityCache.add(entry);
}
}
SecurityRuleEntry entry = securityEntryReader.read(user);
securityCache.add(entry, groups);
}
use of org.xwiki.security.GroupSecurityReference in project xwiki-platform by xwiki.
the class DefaultSecurityCacheLoader method loadUserEntry.
/**
* Load user/group entry in the cache as needed, load related group entries and return the list of all groups
* associated with the given user/group in both the user wiki and the given entity wiki. Groups containing
* (recursively) groups containing the user/group are also listed.
*
* @param user The user/group to load.
* @param userWiki The user wiki. Should correspond to the wiki of the user/group provided above.
* @param entityWiki Only for global user, the wiki of the entity currently evaluated if it differ from the user
* wiki, null otherwise. Local group information of the entity wiki will be evaluated for the user/group to load
* and a shadow user will be made available in that wiki to support access entries.
* @return A collection of groups associated to the requested user/group (both user wiki and entity wiki)
* @throws ParentEntryEvictedException if any of the parent entries of the group were evicted.
* @throws ConflictingInsertionException When different threads have inserted conflicting entries into the cache.
* @throws org.xwiki.security.authorization.AuthorizationException on error.
*/
private Collection<GroupSecurityReference> loadUserEntry(UserSecurityReference user, SecurityReference userWiki, SecurityReference entityWiki) throws ParentEntryEvictedException, ConflictingInsertionException, AuthorizationException {
// First, we try to get the groups of the user from the cache
Collection<GroupSecurityReference> groups = securityCache.getGroupsFor(user, entityWiki);
if (groups != null) {
// Since we have then in the cache, it means that the entry is already loaded
return groups;
}
// Otherwise we have to load the entry
groups = new HashSet<GroupSecurityReference>();
// Public access could not appear in any group, no need to load it carefully, just optimized here
if (user.getOriginalReference() == null) {
if (securityCache.get(user) == null) {
// Main wiki entry should be loaded
getRules(user);
}
if (entityWiki != null) {
// Ensure there is a Public shadow in the subwiki of the checked entity
securityCache.add(new DefaultSecurityShadowEntry(user, entityWiki), null);
}
return groups;
}
// before looking at the group she is a member of in the local wiki.
if (entityWiki != null) {
// First we add the global groups containing that user/group
// Check availability of the information from the user/group entry in the cache
Collection<GroupSecurityReference> globalGroups = securityCache.getGroupsFor(user, null);
Collection<GroupSecurityReference> immediateGroups;
if (globalGroups == null) {
// No luck, the global user does not seems to be in the cache, so we need to load it
globalGroups = new HashSet<>();
immediateGroups = loadUserGroups(user, userWiki, globalGroups);
loadUserEntry(user, immediateGroups);
} else {
immediateGroups = securityCache.getImmediateGroupsFor(user);
}
groups.addAll(globalGroups);
// should be considered indirectly a member of these groups as well
for (GroupSecurityReference group : globalGroups) {
// Check availability of the information from the shadow entry of the global group in the entity wiki
Collection<GroupSecurityReference> localGroups = securityCache.getGroupsFor(group, entityWiki);
if (localGroups == null) {
// No luck, the shadow of the global group in the entity wiki does not seems to be in the cache,
// so we need to load it
localGroups = new HashSet<>();
securityCache.add(new DefaultSecurityShadowEntry(group, entityWiki), loadUserGroups(group, entityWiki, localGroups));
}
groups.addAll(localGroups);
}
Collection<GroupSecurityReference> localGroups = new HashSet<>();
immediateGroups.addAll(loadUserGroups(user, entityWiki, localGroups));
// Store a shadow entry for a global user/group involved in a local wiki
securityCache.add(new DefaultSecurityShadowEntry(user, entityWiki), immediateGroups);
groups.addAll(localGroups);
} else {
// We load the rules concerning the groups of the user, could be either
// the global group of a global user or local group for a local user
// and we finally load that user.
Collection<GroupSecurityReference> localGroups = new HashSet<>();
loadUserEntry(user, loadUserGroups(user, userWiki, localGroups));
groups.addAll(localGroups);
}
// Returns all collected groups for access evaluation
return groups;
}
use of org.xwiki.security.GroupSecurityReference in project xwiki-platform by xwiki.
the class DefaultSecurityCacheLoader method loadAccessEntries.
/**
* Load group entries, and user entries required, to settle the access, settle it,
* add this decision into the cache and return the access.
*
* @param user The user to check access for.
* @param entity The lowest entity providing security rules on the path of the entity to check access for.
* @param ruleEntries The rule entries associated with the above entity.
* @return The access for the user at the entity (equivalent to the one of the entity to check access for).
* @throws ParentEntryEvictedException If one of the parent entries are evicted before the load is completed.
* @throws ConflictingInsertionException When different threads have inserted conflicting entries into the cache.
* @throws org.xwiki.security.authorization.AuthorizationException On error.
*/
private SecurityAccessEntry loadAccessEntries(UserSecurityReference user, SecurityReference entity, Deque<SecurityRuleEntry> ruleEntries) throws ParentEntryEvictedException, ConflictingInsertionException, AuthorizationException {
// userWiki is the wiki of the user
SecurityReference userWiki = user.getWikiReference();
// entityWiki is the wiki of the entity when the user is global and the entity is local
SecurityReference entityWiki = user.isGlobal() ? entity.getWikiReference() : null;
if (entityWiki != null && userWiki.equals(entityWiki)) {
entityWiki = null;
}
// Load user and related groups into the cache (global and shadowed locals) as needed
Collection<GroupSecurityReference> groups = loadUserEntry(user, userWiki, entityWiki);
// Settle the access
SecurityAccessEntry accessEntry = authorizationSettlerProvider.get().settle(user, groups, ruleEntries);
// Store the result into the cache
securityCache.add(accessEntry, entityWiki);
// Return the result
return accessEntry;
}
use of org.xwiki.security.GroupSecurityReference in project xwiki-platform by xwiki.
the class DefaultAuthorizationSettlerTest method testSettleNewRightJustAdded.
@Test
public void testSettleNewRightJustAdded() throws Exception {
Right newRight = getNewTestRight("RightAddedLater", DENY, DENY, true);
XWikiSecurityAccess defaultNewRight = defaultAccess.clone();
defaultNewRight.allow(newRight);
assertAccess("Allow a new right just added now", userRef, docRef, defaultNewRight, authorizationSettler.settle(userRef, Arrays.asList(groupRef), getMockedSecurityRuleEntries("onlyNewRight", docRef, Arrays.asList(Arrays.asList(getMockedSecurityRule("onlyNewRight", Arrays.asList(userRef), Collections.<GroupSecurityReference>emptyList(), Arrays.asList(newRight), RuleState.ALLOW))))));
}
Aggregations