blob: b8dc226f3f8d340d47b3e4c4ee27704c7dd46b3a [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with this
* work for additional information regarding copyright ownership. The ASF
* licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.karaf.webconsole.core.security;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import org.apache.wicket.authorization.strategies.role.Roles;
/**
* An extension of roles to support hierarchical roles. Hierarchy is created by
* splitting dahses in the role names.
*
* The role checking follow the structure with one exception. If assgidned roles
* do not have a "specific" extension then check will pass. For example, if user
* have assigned role "test-role" and component requires role "test-role-one"
* then user will be authorized.
*/
public class HierarchicalRoles {
/**
* Helper class.
*/
class Node {
private Map<String, Node> nodes = new TreeMap<String, Node>();
private String name;
public Node(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Map<String, Node> getNodes() {
return nodes;
}
}
/**
* Assgined roles.
*/
private Map<String, Node> nodes = new TreeMap<String, Node>();
public HierarchicalRoles(Roles roles) {
for (String role : roles) {
String[] path = role.split("-");
createNode(nodes, new ArrayList<String>(Arrays.asList(path)));
}
}
public HierarchicalRoles() {
this(new Roles());
}
public HierarchicalRoles(String roles) {
this(new Roles(roles));
}
private void createNode(Map<String, Node> nodes, List<String> path) {
String name = path.remove(0);
if (!nodes.containsKey(name)) {
nodes.put(name, new Node(name));
}
if (path.size() >= 1) {
createNode(nodes.get(name).nodes, path);
}
}
public boolean hasAnyRole(HierarchicalRoles requested) {
//
if (requested.getNodes().isEmpty()) {
return true;
}
Map<String, Node> requestedNodes = requested.getNodes();
return matchesAny(nodes, requestedNodes);
}
private static boolean matchesAny(Map<String, Node> assignedNodes, Map<String, Node> requestedNodes) {
boolean match = false;
for (Node node : requestedNodes.values()) {
Node assigned = assignedNodes.get(node.getName());
if (assigned != null) {
if (assigned.getNodes().size() > 0) {
match = matchesAny(assigned.getNodes(), node.getNodes());
} else {
match = true;
}
}
}
return match;
}
public Map<String, Node> getNodes() {
return Collections.unmodifiableMap(nodes);
}
}