All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.security.access.hierarchicalroles.RoleHierarchyImplCustom Maven / Gradle / Ivy

package org.springframework.security.access.hierarchicalroles;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.util.StringUtils;

public class RoleHierarchyImplCustom extends org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl {
  private static final Log logger = LogFactory.getLog(RoleHierarchyImplCustom.class);
  private String roleHierarchyStringRepresentation = null;
  private Map> rolesReachableInOneStepMap = null;
  private Map> rolesReachableInOneOrMoreStepsMap = null;
  private long timeout = 10000L;

  /**
   * @see java.util.concurrent.Executors#newSingleThreadExecutor()
   * @see java.util.concurrent.Executors#newCachedThreadPool()
   * @see java.lang.Thread#currentThread()
   * @see java.lang.Thread#interrupt()
   */
  public void setHierarchy(String roleHierarchyStringRepresentation) {
    this.roleHierarchyStringRepresentation = roleHierarchyStringRepresentation;
    logger.debug("setHierarchy() - The following role hierarchy was set: " + roleHierarchyStringRepresentation);
    buildRolesReachableInOneStepMap();

    ExecutorService executorService = Executors.newSingleThreadExecutor();
    Future future = executorService.submit(new Runnable() {
      @Override
      public void run() {
        buildRolesReachableInOneOrMoreStepsMap();
      }
    });
    try {
      future.get(this.timeout, TimeUnit.MILLISECONDS);
    }
    catch (TimeoutException | InterruptedException | ExecutionException e) {
      if (e.getCause() instanceof CycleInRoleHierarchyException) {
        throw (CycleInRoleHierarchyException) e.getCause();
      }
      throw new IllegalStateException(e.getCause() instanceof Throwable ? e.getCause() : e);
    }
    finally {
      future.cancel(true);
    }
  }

  public Collection getReachableGrantedAuthorities(Collection authorities) {
    if (authorities == null || authorities.isEmpty()) {
      return AuthorityUtils.NO_AUTHORITIES;
    }
    Set reachableRoles = new HashSet();
    for (GrantedAuthority authority : authorities) {
      addReachableRoles(reachableRoles, authority);
      Set additionalReachableRoles = getRolesReachableInOneOrMoreSteps(authority);
      if (additionalReachableRoles != null) {
        reachableRoles.addAll(additionalReachableRoles);
      }
    }
    if (logger.isDebugEnabled()) {
      logger.debug("getReachableGrantedAuthorities() - From the roles " + authorities + " one can reach " + reachableRoles + " in zero or more steps.");
    }
    List reachableRoleList = new ArrayList(reachableRoles.size());
    reachableRoleList.addAll(reachableRoles);
    return reachableRoleList;
  }

  // SEC-863
  private void addReachableRoles(Set reachableRoles, GrantedAuthority authority) {
    for (GrantedAuthority testAuthority : reachableRoles) {
      String testKey = testAuthority.getAuthority();
      if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
        return;
      }
    }
    reachableRoles.add(authority);
  }

  // SEC-863
  private Set getRolesReachableInOneOrMoreSteps(GrantedAuthority authority) {
    if (authority.getAuthority() == null) {
      return null;
    }
    for (GrantedAuthority testAuthority : this.rolesReachableInOneOrMoreStepsMap.keySet()) {
      String testKey = testAuthority.getAuthority();
      if ((testKey != null) && (testKey.equals(authority.getAuthority()))) {
        return this.rolesReachableInOneOrMoreStepsMap.get(testAuthority);
      }
    }
    return null;
  }

  private void buildRolesReachableInOneStepMap() {
    this.rolesReachableInOneStepMap = new HashMap>();
    if (StringUtils.hasText(this.roleHierarchyStringRepresentation)) {
      try (BufferedReader bufferedReader = new BufferedReader(new StringReader(this.roleHierarchyStringRepresentation))) {
        for (String readLine; StringUtils.hasText(readLine = bufferedReader.readLine());) {
          for (String string : readLine.split(" and ")) {
            buildRolesReachableInOneStepMap(string);
          }
        }
      }
      catch (IOException e) {
        throw new IllegalStateException(e);
      }
    }
  }

  private void buildRolesReachableInOneStepMap(String roleHierarchyStringRepresentation) {
    if (StringUtils.hasText(roleHierarchyStringRepresentation)) {
      String[] strings = roleHierarchyStringRepresentation.split(" > ");
      for (int i = 1; i < strings.length; i++) {
        String higherRoleString = strings[i - 1].replaceAll("^\\s+|\\s+$", "");
        String lowerRoleString = strings[i].replaceAll("^\\s+|\\s+$", "");
        if (StringUtils.hasText(higherRoleString) && StringUtils.hasText(lowerRoleString)) {
          GrantedAuthority higherRole = new SimpleGrantedAuthority(higherRoleString);
          GrantedAuthority lowerRole = new SimpleGrantedAuthority(lowerRoleString);
          Set rolesReachableInOneStepSet;
          if (!this.rolesReachableInOneStepMap.containsKey(higherRole)) {
            rolesReachableInOneStepSet = new HashSet();
            this.rolesReachableInOneStepMap.put(higherRole, rolesReachableInOneStepSet);
          }
          else {
            rolesReachableInOneStepSet = this.rolesReachableInOneStepMap.get(higherRole);
          }
          addReachableRoles(rolesReachableInOneStepSet, lowerRole);
          logger.debug("buildRolesReachableInOneStepMap() - From role " + higherRole + " one can reach role " + lowerRole + " in one step.");
        }
      }
    }
  }

  private void buildRolesReachableInOneOrMoreStepsMap() {
    this.rolesReachableInOneOrMoreStepsMap = new HashMap>();
    for (GrantedAuthority role : this.rolesReachableInOneStepMap.keySet()) {
      Set rolesToVisitSet = new HashSet();
      if (this.rolesReachableInOneStepMap.containsKey(role)) {
        rolesToVisitSet.addAll(this.rolesReachableInOneStepMap.get(role));
      }
      Set visitedRolesSet = new HashSet();
      while (!rolesToVisitSet.isEmpty()) {
        GrantedAuthority aRole = rolesToVisitSet.iterator().next();
        rolesToVisitSet.remove(aRole);
        addReachableRoles(visitedRolesSet, aRole);
        if (this.rolesReachableInOneStepMap.containsKey(aRole)) {
          Set newReachableRoles = this.rolesReachableInOneStepMap.get(aRole);
          if (rolesToVisitSet.contains(role) || visitedRolesSet.contains(role)) {
            throw new CycleInRoleHierarchyException();
          }
          else {
            rolesToVisitSet.addAll(newReachableRoles);
          }
        }
      }
      this.rolesReachableInOneOrMoreStepsMap.put(role, visitedRolesSet);
      logger.debug("buildRolesReachableInOneOrMoreStepsMap() - From role " + role + " one can reach " + visitedRolesSet + " in one or more steps.");
    }
  }

  public long getTimeout() {
    return timeout;
  }

  public void setTimeout(long timeout) {
    this.timeout = timeout;
  }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy