package org.carlspring.strongbox.users.domain; import org.carlspring.strongbox.data.domain.GenericEntity; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.base.Objects; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Additional user settings (for example, per-repository access settings). * * @author Alex Oreshkevich */ public class AccessModel extends GenericEntity { private static final Logger logger = LoggerFactory.getLogger(AccessModel.class); private Map<String, Collection<String>> repositoryPrivileges; // maps URL tails including wildcards for regular expressions on set of privileges that was assigned // example: // key: storage0/act-releases-1/pro/redsoft/bar/.* // value: {ARTIFACTS_VIEW, ARTIFACTS_RESOLVE, ARTIFACTS_DEPLOY} private Map<String, Collection<String>> urlToPrivilegesMap; private Map<String, Collection<String>> wildCardPrivilegesMap; public AccessModel() { repositoryPrivileges = new HashMap<>(); urlToPrivilegesMap = new HashMap<>(); wildCardPrivilegesMap = new HashMap<>(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; AccessModel that = (AccessModel) o; return Objects.equal(urlToPrivilegesMap, that.urlToPrivilegesMap); } @Override public int hashCode() { return Objects.hashCode(urlToPrivilegesMap); } public Map<String, Collection<String>> getUrlToPrivilegesMap() { return urlToPrivilegesMap; } public void setUrlToPrivilegesMap(Map<String, Collection<String>> urlToPrivilegesMap) { this.urlToPrivilegesMap = urlToPrivilegesMap; } public Map<String, Collection<String>> getWildCardPrivilegesMap() { return wildCardPrivilegesMap; } public void setWildCardPrivilegesMap(Map<String, Collection<String>> wildCardPrivilegesMap) { this.wildCardPrivilegesMap = wildCardPrivilegesMap; } public Map<String, Collection<String>> getRepositoryPrivileges() { return repositoryPrivileges; } public void setRepositoryPrivileges(Map<String, Collection<String>> repositoryPrivileges) { this.repositoryPrivileges = repositoryPrivileges; } public void obtainPrivileges() { if (urlToPrivilegesMap != null && !urlToPrivilegesMap.isEmpty()) { final List<String> keysToRemove = new LinkedList<>(); urlToPrivilegesMap.entrySet() .stream() .filter(entry -> entry.getKey() .endsWith(".*") || entry.getKey() .endsWith("**")) .forEach(entry -> { String newUrl = entry.getKey() .substring(0, entry.getKey() .length() - 3); List<String> newPrivileges = new ArrayList<>(entry.getValue()); wildCardPrivilegesMap.put(newUrl, newPrivileges); keysToRemove.add(entry.getKey()); }); keysToRemove.forEach(key -> urlToPrivilegesMap.remove(key)); keysToRemove.clear(); } } public Collection<String> getPathPrivileges(String url) { Set<String> privileges = new HashSet<>(); // if repository privileges covers URL, assign it's privileges by default repositoryPrivileges.forEach((key, value) -> { if (url.startsWith(key)) { privileges.addAll(value); } }); // if URL covered by exact path mapping add it's privileges if (urlToPrivilegesMap.containsKey(url)) { privileges.addAll(urlToPrivilegesMap.get(url)); } // if URL covered by wildcard mapping add it's privileges if (!wildCardPrivilegesMap.isEmpty()) { wildCardPrivilegesMap.entrySet() .stream() .filter(entry -> url.startsWith(entry.getKey())) .findAny() .ifPresent(entry -> privileges.addAll(entry.getValue())); } logger.debug("Calculated privileges for \n\t" + url + "\n\t" + privileges); return privileges; } @Override public String toString() { final StringBuilder sb = new StringBuilder("\nAccessModel {"); prettyPrintMap(sb, "urlToPrivilegesMap", urlToPrivilegesMap); prettyPrintMap(sb, "repositoryPrivileges", repositoryPrivileges); prettyPrintMap(sb, "wildCardPrivilegesMap", wildCardPrivilegesMap); sb.append("\n}"); return sb.toString(); } private void prettyPrintMap(StringBuilder sb, String name, Map<?, ?> map) { if (map != null && !map.isEmpty()) { sb.append("\n\t") .append(name) .append(" = {"); map.entrySet() .forEach(entry -> sb.append("\n\t\t") .append(entry.getKey()) .append("\t\t-> ") .append(entry.getValue())); sb.append("\n\t}"); } } }