tech.beshu.ror.acl.blocks.rules.impl.GroupsProviderAuthorizationAsyncRule.java Source code

Java tutorial

Introduction

Here is the source code for tech.beshu.ror.acl.blocks.rules.impl.GroupsProviderAuthorizationAsyncRule.java

Source

/*
 *    This file is part of ReadonlyREST.
 *
 *    ReadonlyREST is free software: you can redistribute it and/or modify
 *    it under the terms of the GNU General Public License as published by
 *    the Free Software Foundation, either version 3 of the License, or
 *    (at your option) any later version.
 *
 *    ReadonlyREST is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with ReadonlyREST.  If not, see http://www.gnu.org/licenses/
 */

package tech.beshu.ror.acl.blocks.rules.impl;

import com.google.common.collect.Sets;
import tech.beshu.ror.acl.blocks.rules.AsyncAuthorization;
import tech.beshu.ror.acl.definitions.groupsproviders.GroupsProviderServiceClient;
import tech.beshu.ror.acl.definitions.groupsproviders.GroupsProviderServiceClientFactory;
import tech.beshu.ror.commons.domain.LoggedUser;
import tech.beshu.ror.commons.shims.es.ESContext;
import tech.beshu.ror.commons.utils.MatcherWithWildcards;
import tech.beshu.ror.settings.rules.GroupsProviderAuthorizationRuleSettings;

import java.util.Set;
import java.util.concurrent.CompletableFuture;

public class GroupsProviderAuthorizationAsyncRule extends AsyncAuthorization {

    private final GroupsProviderAuthorizationRuleSettings settings;
    private final GroupsProviderServiceClient client;
    private final MatcherWithWildcards usersMatcher;

    public GroupsProviderAuthorizationAsyncRule(GroupsProviderAuthorizationRuleSettings settings,
            GroupsProviderServiceClientFactory factory, ESContext context) {
        super(context);
        this.settings = settings;
        this.client = factory.getClient(settings.getUserGroupsProviderSettings());
        this.usersMatcher = new MatcherWithWildcards(settings.getUsers());
    }

    @Override
    protected CompletableFuture<Boolean> authorize(LoggedUser user) {
        if (!usersMatcher.match(user.getId())) {
            return CompletableFuture.completedFuture(false);
        }
        return client.fetchGroupsFor(user)
                // No wildcard matching for configured groups, but users can be declared as wildcards.
                .thenApply(fetchedGroupsForUser -> {

                    // Exit early if resolved groups have nothing to do with the ones configured in this rule
                    Sets.SetView<String> intersection = Sets.intersection(settings.getGroups(),
                            Sets.newHashSet(fetchedGroupsForUser));
                    if (intersection.isEmpty()) {
                        return false;
                    }

                    System.out.println("user: " + user.getId() + " has groups: " + fetchedGroupsForUser
                            + ", intersected: " + intersection);

                    // Exit early if the request has a current group that does not belong to this rule, or is not resolved for user
                    if (user.getCurrentGroup().isPresent()) {
                        String currGroup = user.getCurrentGroup().get();
                        System.out.println("found current group: " + currGroup);
                        if (!intersection.contains(currGroup)) {
                            System.out
                                    .println("current group in header does not match any available groups in rule "
                                            + currGroup);
                            return false;
                        }
                    }

                    // Set current group as the first of the list, if was absent (this will surface on the response header)
                    else {
                        String curGroup = intersection.immutableCopy().iterator().next();
                        System.out.println("setting current group: " + curGroup);
                        user.setCurrentGroup(curGroup);
                    }

                    // Exploring all the __old_ACL for available groups for this user, known what their resolved groups are, and what the __old_ACL has to offer for the user
                    Set<String> matchingUserPatterns = new MatcherWithWildcards(
                            settings.getUserGroupsProviderSettings().getUser2availGroups().keySet())
                                    .matchingMatchers(Sets.newHashSet(user.getId()));
                    Set<String> availGroupsForUser = Sets.newHashSet();
                    for (String up : matchingUserPatterns) {
                        availGroupsForUser
                                .addAll(settings.getUserGroupsProviderSettings().getUser2availGroups().get(up));
                    }
                    availGroupsForUser = Sets.intersection(availGroupsForUser, fetchedGroupsForUser);
                    System.out.println(
                            "adding available groups for user " + user.getId() + ": " + availGroupsForUser);

                    user.addAvailableGroups(availGroupsForUser);

                    return true;
                });
    }

    @Override
    public String getKey() {
        return settings.getName();
    }

}