Package org.apache.clerezza.platform.usermanager

Source Code of org.apache.clerezza.platform.usermanager.UserManagerImpl

/*
* 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.clerezza.platform.usermanager;

import java.io.UnsupportedEncodingException;
import java.security.AccessController;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Policy;
import java.security.PrivilegedAction;
import java.security.SecurityPermission;
import java.util.Collection;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.concurrent.locks.Lock;
import org.apache.clerezza.platform.config.SystemConfig;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.clerezza.platform.graphprovider.content.ContentGraphProvider;
import org.apache.clerezza.rdf.core.BNode;
import org.apache.clerezza.rdf.core.MGraph;
import org.apache.clerezza.rdf.core.NonLiteral;
import org.apache.clerezza.rdf.core.PlainLiteral;
import org.apache.clerezza.rdf.core.Resource;
import org.apache.clerezza.rdf.core.Triple;
import org.apache.clerezza.rdf.core.UriRef;
import org.apache.clerezza.rdf.core.access.LockableMGraph;
import org.apache.clerezza.rdf.core.access.SecuredMGraph;
import org.apache.clerezza.rdf.core.access.TcManager;
import org.apache.clerezza.rdf.core.impl.PlainLiteralImpl;
import org.apache.clerezza.rdf.core.impl.SimpleMGraph;
import org.apache.clerezza.rdf.core.impl.TripleImpl;
import org.apache.clerezza.rdf.ontologies.DC;
import org.apache.clerezza.rdf.ontologies.FOAF;
import org.apache.clerezza.rdf.ontologies.OSGI;
import org.apache.clerezza.rdf.ontologies.PERMISSION;
import org.apache.clerezza.rdf.ontologies.PLATFORM;
import org.apache.clerezza.rdf.ontologies.RDF;
import org.apache.clerezza.rdf.ontologies.SIOC;
import org.apache.clerezza.rdf.utils.GraphNode;

/**
* @author hasan, tio
*/
@Component
@Service(value=UserManager.class)
public class UserManagerImpl implements UserManager {

  @Reference
  private ContentGraphProvider cgProvider;

  @Reference
  TcManager tcManager;

  private final Logger logger = LoggerFactory.getLogger(getClass());

  @Reference(target = SystemConfig.SYSTEM_GRAPH_FILTER)
  private MGraph securedSystemGraph;

  private LockableMGraph getSystemGraph() {
    return ((SecuredMGraph) securedSystemGraph).getUnsecuredMGraph();
  }

  @Override
  public void storeRole(String title) {
    if (title == null) {
      return;
    }
    if (getRoleByTitle(title) != null) {
      return;
    }
    BNode role = new BNode();
    LockableMGraph systemGraph = getSystemGraph();
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      systemGraph.add(new TripleImpl(role, RDF.type, PERMISSION.Role));
      systemGraph.add(new TripleImpl(role, DC.title,
          new PlainLiteralImpl(title)));
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public NonLiteral getRoleByTitle(String title) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      Iterator<Triple> triples = systemGraph.filter(null, DC.title,
          new PlainLiteralImpl(title));
      NonLiteral role = null;
      while (triples.hasNext()) {
        role = triples.next().getSubject();
        if (systemGraph.filter(role, RDF.type, PERMISSION.Role).hasNext()) {
          return role;
        }
      }
    } finally {
      readLock.unlock();
    }
    return null;
  }

  @Override
  public boolean roleExists(String title) {
    return getRoleByTitle(title) != null;
  }

  @Override
  public Iterator<NonLiteral> getRoles() {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      final Iterator<NonLiteral> allRolesIter = getResourcesOfType(PERMISSION.Role);
      final Set<NonLiteral> allRolesSet = new HashSet<NonLiteral>();
      while (allRolesIter.hasNext()) {
        allRolesSet.add(allRolesIter.next());
      }
      final Set<NonLiteral> nonBaseRolesSet = new HashSet<NonLiteral>();
      for (NonLiteral role : allRolesSet) {
        if (!systemGraph.filter(role, RDF.type, PERMISSION.BaseRole).hasNext()) {
          nonBaseRolesSet.add(role);
        }
      }
      return nonBaseRolesSet.iterator();
    } finally {
      readLock.unlock();
    }   
  }

  @Override
  public Iterator<NonLiteral> getRolesOfUser(NonLiteral user){
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      final Iterator<Triple> triples = systemGraph.filter(user,SIOC.has_function, null);
      Set<NonLiteral> userRoles = new HashSet<NonLiteral>();
      while (triples.hasNext()) {
        userRoles.add((NonLiteral) triples.next().getObject());
      }
      return userRoles.iterator();
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public void deleteRole(String title) {
    if (title == null) {
      return;
    }

    NonLiteral role = getRoleByTitle(title);
    if (role == null) {
      return;
    }
    if (isBaseRole(role)) {
      return;
    }
    deleteTriplesOfASubject(role);
  }

  private boolean isBaseRole(NonLiteral role) {
    LockableMGraph systemGraph = getSystemGraph();
    GraphNode roleNode = new GraphNode(role, systemGraph);
    Lock readLock = roleNode.readLock();
    readLock.lock();
    try {
      return roleNode.hasProperty(RDF.type, PERMISSION.BaseRole);
    } finally {
      readLock.unlock();
    }
   
  }

  private void deleteTriplesOfASubject(NonLiteral subject) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      Iterator<Triple> triples = systemGraph.filter(subject, null, null);
      while (triples.hasNext()) {
        triples.next();
        triples.remove();
      }
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public void assignPermissionsToRole(String title,
      List<String> permissionEntries) {

    if (title == null) {
      return;
    }

    addPermissionEntriesForARole(
        getRoleByTitle(title), title,
        permissionEntries);
  }

  private void addPermissionEntriesForARole(NonLiteral role,
      String id, List<String> permissionEntries) {
    AccessController.checkPermission(new SecurityPermission("getPolicy"));
    if (role == null) {
      logger.debug("Cannot assign permissions: {} does not exist", id);
      return;
    }
    if (permissionEntries.isEmpty()) {
      return;
    }
    LockableMGraph systemGraph = getSystemGraph();
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      for (String permissionEntry : permissionEntries) {
        if (permissionEntry.trim().length() == 0) {
          continue;
        }
        systemGraph.add(new TripleImpl(role, PERMISSION.hasPermission,
            getPermissionOfAJavaPermEntry(permissionEntry)));
      }
    } finally {
      writeLock.unlock();
    }
    //refresh the policy so it will recheck the permissions
    Policy.getPolicy().refresh();
  }

  /**
   * Get the permission node having the specified java permission entry.
   * If the node does not exist, a new node is created.
   *
   * @param graph
   * @param permissionString the specified java permission entry
   * @return permission node
   */
  private NonLiteral getPermissionOfAJavaPermEntry(
      String permissionString) {
    LockableMGraph systemGraph = getSystemGraph();
    PlainLiteral javaPermEntry = new PlainLiteralImpl(permissionString);
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      Iterator<Triple> javaPermTriples = systemGraph.filter(null,
          PERMISSION.javaPermissionEntry, javaPermEntry);
      if (javaPermTriples.hasNext()) {
        return javaPermTriples.next().getSubject();
      }
    } finally {
      readLock.unlock();
    }

    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      BNode result = new BNode();
      systemGraph.add(new TripleImpl(result,
          PERMISSION.javaPermissionEntry, javaPermEntry));
      return result;
    } finally {
      writeLock.unlock();
    }
  }

  @Override
  public Iterator<NonLiteral> getPermissionsOfRole(NonLiteral role) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      final Iterator<Triple> triples = systemGraph.filter(role,
          PERMISSION.hasPermission, null);
      Set<NonLiteral> permissions = new HashSet<NonLiteral>();
      while (triples.hasNext()) {
        permissions.add((NonLiteral) triples.next().getObject());
      }
      return permissions.iterator();
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public void deletePermissionsOfRole(String title,
      List<String> permissionEntries) {

    if (title == null) {
      return;
    }

    deletePermissionEntriesOfARole(
        getRoleByTitle(title), title,
        permissionEntries);
  }

  private void deletePermissionEntriesOfARole(NonLiteral role,
      String id, List<String> permissionEntries) {
    AccessController.checkPermission(new SecurityPermission("getPolicy"));
    if (role == null) {
      logger.debug("Cannot delete permissions: {} does not exist", id);
      return;
    }
    if (permissionEntries.isEmpty()) {
      return;
    }
    LockableMGraph systemGraph = getSystemGraph();
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      for (String permissionEntry : permissionEntries) {
        NonLiteral permission = getPermissionOfAJavaPermEntry(permissionEntry);
        systemGraph.remove(new TripleImpl(role, PERMISSION.hasPermission,
            permission));
      }
    } finally {
      writeLock.unlock();
    }
    //refresh the policy so it will recheck the permissions
    Policy.getPolicy().refresh();
  }

  @Override
  public void deleteAllPermissionsOfRole(String title) {
    if (title == null) {
      return;
    }

    deleteAllPermissionEntriesOfARole(
        getRoleByTitle(title));
  }

  private void deleteAllPermissionEntriesOfARole(NonLiteral role) {
    AccessController.checkPermission(new SecurityPermission("getPolicy"));
    if (role == null) {
      return;
    }
    LockableMGraph systemGraph = getSystemGraph();
    GraphNode graphNode = new GraphNode(role, systemGraph);
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      graphNode.deleteProperties(PERMISSION.hasPermission);
    } finally {
      writeLock.unlock();
    }   
    //refresh the policy so it will recheck the permissions
    Policy.getPolicy().refresh();
  }

  @Override
  public void storeUser(String name, String email, String password,
      List<String> assignedRoles, String pathPrefix) {

    if (name == null) {
      return;
    }

    if (getUserByUserName(name) != null) {
      throw new UserAlreadyExistsException(name);
    }
    if (email != null) {
      String storedName = getNameByEmail(email);
      if (storedName != null && !name.equals(storedName)) {
        throw new EmailAlreadyAssignedException(email, storedName);
      }
    }
    BNode user = new BNode();
    LockableMGraph systemGraph = getSystemGraph();
    Lock writeLock = systemGraph.getLock().writeLock();
    writeLock.lock();
    try {
      systemGraph.add(new TripleImpl(user, RDF.type, FOAF.Agent));
      systemGraph.add(new TripleImpl(user, PLATFORM.userName,
          new PlainLiteralImpl(name)));
      if (email != null) {
        systemGraph.add(new TripleImpl(user, FOAF.mbox,
            new UriRef("mailto:" + email)));
      }
      if (password != null) {
        try {
          String pswSha1 = bytes2HexString(MessageDigest.getInstance("SHA1").digest(password.getBytes("UTF-8")));
          systemGraph.add(new TripleImpl(user, PERMISSION.passwordSha1, new PlainLiteralImpl(pswSha1)));
        } catch (UnsupportedEncodingException ex) {
          throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
          throw new RuntimeException(ex);
        }
      }
      if (pathPrefix != null && pathPrefix.trim().length() != 0) {
        systemGraph.add(new TripleImpl(user, OSGI.agent_path_prefix,
            new PlainLiteralImpl(pathPrefix)));
      }
      if (!assignedRoles.isEmpty()) {
        addRolesToUser(assignedRoles, user);
      }     
    } finally {
      writeLock.unlock();
    }
   
  }

  /**
   *
   * @param graph
   * @param email
   * @return
   *    null if the email does not exist in the graph,
   *    otherwise returns the name of the user who owns the email
   * @throws org.apache.clerezza.platform.usermanager.UserHasNoNameException
   */
  @Override
  public String getNameByEmail(String email)
      throws UserHasNoNameException {
    if (email == null) {
      return null;
    }
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      Iterator<Triple> triples = systemGraph.filter(null, FOAF.mbox,
          new UriRef("mailto:" + email));
      if (!triples.hasNext()) {
        return null;
      }
      NonLiteral user = triples.next().getSubject();
      triples = systemGraph.filter(user, PLATFORM.userName, null);
      if (!triples.hasNext()) {
        throw new UserHasNoNameException("User with email address" + email
            + " does not have a name");
      }
      return ((PlainLiteral) triples.next().getObject()).getLexicalForm();
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public void updateUser(String name, String email, String password,
      Collection<String> assignedRoles, String pathPrefix) {

    AccessController.checkPermission(new SecurityPermission("getPolicy"));
    if (name == null) {
      throw new IllegalArgumentException("userName may not be null");
    }
    NonLiteral user = getUserByUserName(name);
    if (user == null) {
      throw new UserNotExistsException(name);
    }
    LockableMGraph systemGraph = getSystemGraph();
    GraphNode userGraphNode = new GraphNode(user, systemGraph);
    Lock writeLock = userGraphNode.writeLock();
    writeLock.lock();
    try {
      if (email != null) {
        updateProperty(userGraphNode, FOAF.mbox, new UriRef("mailto:" + email));
      }

      if (password != null) {
        try {
          String pswSha1 = bytes2HexString(MessageDigest.getInstance("SHA1").digest(password.getBytes("UTF-8")));
          updateProperty(userGraphNode, PERMISSION.passwordSha1, new PlainLiteralImpl(pswSha1));
        } catch (UnsupportedEncodingException ex) {
          throw new RuntimeException(ex);
        } catch (NoSuchAlgorithmException ex) {
          throw new RuntimeException(ex);
        }
      }
      if (pathPrefix != null && pathPrefix.trim().length() != 0) {
        updateProperty(userGraphNode, OSGI.agent_path_prefix,
            new PlainLiteralImpl(pathPrefix));
      }
      if (!assignedRoles.isEmpty()) {
        userGraphNode.deleteProperties(SIOC.has_function);
        addRolesToUser(assignedRoles, (NonLiteral) userGraphNode.getNode());
        //refresh the policy so it will recheck the permissions
        Policy.getPolicy().refresh();
      }
    } finally {
      writeLock.unlock();
    }
  }

  private void addRolesToUser(Collection<String> assignedRoles, NonLiteral user) throws RoleUnavailableException {
    LockableMGraph systemGraph = getSystemGraph();
    for (String roleTitle : assignedRoles) {
      // skip empty strings
      if ((roleTitle == null) || (roleTitle.trim().length() == 0)) {
        continue;
      }
      NonLiteral role = getRoleByTitle(roleTitle);
      if (role == null) {
        throw new RoleUnavailableException(roleTitle);
      }
      systemGraph.add(new TripleImpl(user, SIOC.has_function, role));
    }
  }

  private void updateProperty(GraphNode node, UriRef predicate, Resource object) {
    node.deleteProperties(predicate);
    node.addProperty(predicate, object);
  }

  @Override
  public boolean nameExists(String name) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      return systemGraph.filter(null, PLATFORM.userName,
        new PlainLiteralImpl(name)).hasNext();
    } finally {
      readLock.unlock();
    }   
  }

  @Override
  public boolean emailExists(String email) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      return systemGraph.filter(null, FOAF.mbox,
          new UriRef("mailto:" + email)).hasNext();
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public NonLiteral getUserByName( String name) {
    return getUserByUserName(name);
  }

  @Override
  public Iterator<NonLiteral> getUsers() {
    return getResourcesOfType(FOAF.Agent);
  }

  private Iterator<NonLiteral> getResourcesOfType(UriRef type) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      final Iterator<Triple> triples = systemGraph.filter(null, RDF.type, type);
      Set<NonLiteral> userRoles = new HashSet<NonLiteral>();
      while (triples.hasNext()) {
        userRoles.add(triples.next().getSubject());
      }
      return userRoles.iterator();
    } finally {
      readLock.unlock();
    }
  }

  @Override
  public void deleteUser(String name) {
    if (name == null) {
      return;
    }

    NonLiteral user = getUserByUserName(name);
    if (user != null) {
      deleteTriplesOfASubject(user);
    }
  }

  @Override
  public void assignPermissionsToUser(String name,
      List<String> permissionEntries) {

    if (name == null) {
      return;
    }

    addPermissionEntriesForARole(
        getUserByUserName(name), name,
        permissionEntries);
  }

  @Override
  public Iterator<NonLiteral> getPermissionsOfUser(NonLiteral user) {
    return getPermissionsOfRole(user);
  }

  @Override
  public void deletePermissionsOfUser(String name,
      List<String> permissionEntries) {

    if (name == null) {
      return;
    }

    deletePermissionEntriesOfARole(
        getUserByUserName(name), name,
        permissionEntries);
  }

  @Override
  public void deleteAllPermissionsOfUser(String name) {
    if (name == null) {
      return;
    }

    deleteAllPermissionEntriesOfARole(
        getUserByUserName(name));
  }

  /**
   * @param bytes
   *    array of bytes to be converted to a String of hexadecimal numbers
   * @return
   *    String of hexadecimal numbers representing the byte array
   */
  private char[] HEXDIGITS = "0123456789abcdef".toCharArray();

  private String bytes2HexString(byte[] bytes) {
    char[] result = new char[bytes.length << 1];
    for (int i = 0, j = 0; i < bytes.length; i++) {
      result[j++] = HEXDIGITS[bytes[i] >> 4 & 0xF];
      result[j++] = HEXDIGITS[bytes[i] & 0xF];
    }
    return new String(result);
  }

  @Override
  public GraphNode getUserInSystemGraph(final String name) {
    LockableMGraph systemGraph = getSystemGraph();
    NonLiteral user = getUserByUserName(name);
    if (user != null) {
      return new GraphNode(user, systemGraph);
    } else {
      return null;
    }
  }

  @Override
  public GraphNode getUserInContentGraph(final String name) {
    final LockableMGraph contentGraph = (LockableMGraph) cgProvider.getContentGraph();
    Iterator<Triple> triples = contentGraph.filter(null, PLATFORM.userName,
        new PlainLiteralImpl(name));
    GraphNode resultNode = null;
    if (triples.hasNext()) {
      Lock readLock = contentGraph.getLock().readLock();
      readLock.lock();
      try {
        resultNode = new GraphNode(triples.next().getSubject(), contentGraph);
      } finally {
        readLock.unlock();
      }     
    } else {
      NonLiteral user = AccessController.doPrivileged(
          new PrivilegedAction<NonLiteral>() {

            @Override
            public NonLiteral run() {
              return getUserByUserName(name);
            }
          });
      if (user != null) {
        Lock writeLock = contentGraph.getLock().writeLock();
        writeLock.lock();
        try {
          resultNode = new GraphNode(new BNode(), contentGraph);
        resultNode.addProperty(PLATFORM.userName,
            new PlainLiteralImpl(name));
        } finally {
          writeLock.unlock();
        }
       
      }
    }
    return resultNode;
  }

  @Override
  public GraphNode getUserGraphNode(final String name) {
    LockableMGraph systemGraph = getSystemGraph();
    NonLiteral user = getUserByUserName(name);
    if (user != null) {
      GraphNode userNodeInSystemGraph =
          new GraphNode(getUserByUserName(name), systemGraph);
      MGraph copiedUserContext = new SimpleMGraph(userNodeInSystemGraph.getNodeContext());
      return new GraphNode(userNodeInSystemGraph.getNode(),
          copiedUserContext);
    } else {
      return null;
    }
  }

  private NonLiteral getUserByUserName(String name) {
    LockableMGraph systemGraph = getSystemGraph();
    Lock readLock = systemGraph.getLock().readLock();
    readLock.lock();
    try {
      Iterator<Triple> triples = systemGraph.filter(null, PLATFORM.userName,
          new PlainLiteralImpl(name));
      if (triples.hasNext()) {
        return triples.next().getSubject();
      }
      return null;
    } finally {
      readLock.unlock();
    }

  }
}
TOP

Related Classes of org.apache.clerezza.platform.usermanager.UserManagerImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.