Search in sources :

Example 6 with GroupSecurityReference

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;
}
Also used : ArrayList(java.util.ArrayList) GroupSecurityReference(org.xwiki.security.GroupSecurityReference)

Example 7 with GroupSecurityReference

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);
}
Also used : AbstractSecurityRuleEntry(org.xwiki.security.authorization.internal.AbstractSecurityRuleEntry) SecurityRuleEntry(org.xwiki.security.authorization.SecurityRuleEntry) GroupSecurityReference(org.xwiki.security.GroupSecurityReference) SecurityReference(org.xwiki.security.SecurityReference) UserSecurityReference(org.xwiki.security.UserSecurityReference)

Example 8 with GroupSecurityReference

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;
}
Also used : GroupSecurityReference(org.xwiki.security.GroupSecurityReference) HashSet(java.util.HashSet)

Example 9 with GroupSecurityReference

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;
}
Also used : SecurityAccessEntry(org.xwiki.security.authorization.SecurityAccessEntry) GroupSecurityReference(org.xwiki.security.GroupSecurityReference) SecurityReference(org.xwiki.security.SecurityReference) UserSecurityReference(org.xwiki.security.UserSecurityReference) GroupSecurityReference(org.xwiki.security.GroupSecurityReference)

Example 10 with GroupSecurityReference

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))))));
}
Also used : Right(org.xwiki.security.authorization.Right) GroupSecurityReference(org.xwiki.security.GroupSecurityReference) Test(org.junit.Test)

Aggregations

GroupSecurityReference (org.xwiki.security.GroupSecurityReference)20 UserSecurityReference (org.xwiki.security.UserSecurityReference)10 SecurityReference (org.xwiki.security.SecurityReference)9 ArrayList (java.util.ArrayList)6 Test (org.junit.Test)5 Right (org.xwiki.security.authorization.Right)4 SecurityRule (org.xwiki.security.authorization.SecurityRule)4 SecurityRuleEntry (org.xwiki.security.authorization.SecurityRuleEntry)4 HashSet (java.util.HashSet)3 DocumentReference (org.xwiki.model.reference.DocumentReference)2 SecurityAccessEntry (org.xwiki.security.authorization.SecurityAccessEntry)2 SecurityEntry (org.xwiki.security.authorization.SecurityEntry)2 SecurityShadowEntry (org.xwiki.security.authorization.cache.SecurityShadowEntry)2 AbstractSecurityRuleEntry (org.xwiki.security.authorization.internal.AbstractSecurityRuleEntry)2 ArrayDeque (java.util.ArrayDeque)1 Collection (java.util.Collection)1 LinkedList (java.util.LinkedList)1 Matcher (org.hamcrest.Matcher)1 InvocationOnMock (org.mockito.invocation.InvocationOnMock)1 WikiReference (org.xwiki.model.reference.WikiReference)1