/**
* Copyright 2010 JBoss Inc
*
* Licensed 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.drools.repository.security;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.PropertyIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Value;
import org.drools.repository.RulesRepository;
import org.drools.repository.RulesRepositoryException;
/**
* Deals with storing permissions for data and so on.
* @author Michael Neale
*/
public class PermissionManager {
private RulesRepository repository;
public PermissionManager(RulesRepository repo) {
this.repository = repo;
}
/**
* Save the users permissions.
* @param userName = obviously, the user name.
* @param perms - a map of the role type to the targets that it applies to.
* eg: package.admin => PACKAGE UUID
* analyst => category path
* ADMIN => empty (no list needed for admin)
* @throws RepositoryException
*/
public void updateUserPermissions(String userName, Map<String, List<String>> perms) {
if (!isValideUserName(userName)) {
return;
}
try {
Node permsNode = getUserPermissionNode(userName);
permsNode.remove(); //remove this so we get a fresh set
permsNode = getUserPermissionNode(userName).addNode("jcr:content", "nt:unstructured");
for (Iterator<Map.Entry<String, List<String>>> iterator = perms.entrySet().iterator(); iterator.hasNext();) {
Map.Entry<String, List<String>> en = iterator.next();
String perm = en.getKey();
List<String> targets = en.getValue();
if (targets == null) targets = new ArrayList<String>();
permsNode.setProperty(perm, targets.toArray(new String[targets.size()]));
}
this.repository.save();
} catch (RepositoryException e) {
throw new RulesRepositoryException(e);
}
}
public void createUser(String userName) {
if (!isValideUserName(userName)) {
throw new RulesRepositoryException("Invalide user name");
}
if (containsUser(userName)) {
throw new RulesRepositoryException("User name [" + userName + "] already exists");
}
try {
Node permsNode = getUserPermissionNode(userName);
permsNode.remove(); //remove this so we get a fresh set
permsNode = getUserPermissionNode(userName).addNode("jcr:content", "nt:unstructured");
this.repository.save();
} catch (RepositoryException e) {
throw new RulesRepositoryException(e);
}
}
private boolean containsUser(String userName) {
try {
Node userRoot = getUsersRootNode(getRootNode(repository));
if (userRoot.hasNode(userName)) {
return true;
}
} catch (RepositoryException e) {
}
return false;
}
private Node getUserPermissionNode(String userName)
throws RepositoryException {
Node permsNode = getNode(getUserInfoNode(userName, repository), "permissions", "nt:file");
return permsNode;
}
/** get the specified user info node (it is an nt:folder type) */
public static Node getUserInfoNode(String userName, RulesRepository repo) throws RepositoryException {
Node root = getRootNode(repo);
return getNode(getUsersRootNode(root), userName, "nt:folder");
}
/** The root node of the repository */
public static Node getRootNode(RulesRepository repo) throws RepositoryException {
return repo.getSession().getRootNode().getNode(RulesRepository.RULES_REPOSITORY_NAME);
}
/**
* Get the top node for "user_info"
* @throws RepositoryException
*/
public static Node getUsersRootNode(Node root) throws RepositoryException {
return getNode(root, "user_info", "nt:folder");
}
/**
* obtain a mapping of permissions for a given user.
* @throws RepositoryException
*/
public Map<String, List<String>> retrieveUserPermissions(String userName) {
try {
Map<String, List<String>> result = new HashMap<String, List<String>>(10);
if (!isValideUserName(userName)) {
return result;
}
if (!getUserPermissionNode(userName).hasNode("jcr:content")) {
return result;
}
Node permsNode = getUserPermissionNode(userName).getNode("jcr:content");
PropertyIterator it = permsNode.getProperties();
while (it.hasNext()) {
Property p = (Property) it.next();
String name = p.getName();
if (!name.startsWith("jcr")) {
if (p.getDefinition().isMultiple()) {
Value[] vs = p.getValues();
List<String> perms = new ArrayList<String>();
for (int i = 0; i < vs.length; i++) {
perms.add(vs[i].getString());
}
result.put(name, perms);
} else {
Value v = p.getValue();
List<String> perms = new ArrayList<String>(1);
perms.add(v.getString());
result.put(name, perms);
}
}
}
return result;
} catch (RepositoryException e) {
throw new RulesRepositoryException(e);
}
}
/**
* Gets or creates a node.
*/
public static Node getNode(Node node, String name, String nodeType) throws RepositoryException {
Node permsNode;
if (!node.hasNode(name)) {
permsNode = node.addNode(name, nodeType);
} else {
permsNode = node.getNode(name);
}
return permsNode;
}
/**
* Returns a list of users and their permissions types for display.
* The Map maps:
*
* userName => [list of permission types, eg admin, package.admin etc... no IDs]
* For display purposes only.
* @throws RepositoryException
*/
public Map<String, List<String>> listUsers() {
try {
Map<String, List<String>> listing = new HashMap<String, List<String>>();
Node root = getRootNode(this.repository);
Node usersNode = getUsersRootNode(root);
NodeIterator users = usersNode.getNodes();
while (users.hasNext()) {
Node userNode = (Node) users.next();
listing.put(userNode.getName(), listOfPermTypes(userNode));
}
return listing;
} catch (RepositoryException e) {
throw new RulesRepositoryException(e);
}
}
private List<String> listOfPermTypes(Node userNode) throws RepositoryException {
List<String> permTypes = new ArrayList<String>();
Node permsNode = getNode(userNode, "permissions", "nt:file");
Node content = getNode(permsNode, "jcr:content", "nt:unstructured");
PropertyIterator perms = content.getProperties();
while (perms.hasNext()) {
Property p = (Property) perms.next();
String name = p.getName();
if (!name.startsWith("jcr")) {
permTypes.add(name);
}
}
return permTypes;
}
void deleteAllUsers() throws RepositoryException {
Node root = getRootNode(this.repository);
getUsersRootNode(root).remove();
}
public void removeUserPermissions(String userName) {
if (!isValideUserName(userName)) {
return;
}
try {
Node permsNode = getUserPermissionNode(userName);
permsNode.getParent().remove(); //remove this so we get a fresh set
} catch (RepositoryException e) {
throw new RulesRepositoryException(e);
}
}
private boolean isValideUserName(String userName) {
if("".equals(userName.trim()) || userName.trim().length() == 0) {
return false;
}
return true;
}
}