Package eu.planets_project.ifr.core.security.impl.services

Source Code of eu.planets_project.ifr.core.security.impl.services.UserManagerImpl

/**
*
*/
package eu.planets_project.ifr.core.security.impl.services;

import java.security.Principal;
import java.security.acl.Group;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Logger;

import javax.annotation.Resource;
import javax.annotation.security.PermitAll;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Local;
import javax.ejb.Remote;
import javax.ejb.SessionContext;
import javax.ejb.Stateless;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import javax.rmi.PortableRemoteObject;
import javax.security.auth.Subject;

import org.jboss.annotation.ejb.LocalBinding;
import org.jboss.annotation.ejb.RemoteBinding;
import org.jboss.annotation.security.SecurityDomain;

import eu.planets_project.ifr.core.common.mail.PlanetsMailMessage;
import eu.planets_project.ifr.core.security.api.model.Role;
import eu.planets_project.ifr.core.security.api.model.User;
import eu.planets_project.ifr.core.security.api.services.UserManager;
import eu.planets_project.ifr.core.security.impl.model.RoleImpl;
import eu.planets_project.ifr.core.security.impl.model.UserImpl;

/**
* This is the concrete implementation of the User Manager.
* It conforms to a single interface, the UserManagerInterface.
* It exports this interface locally, remotely, and (eventually) over web services too.
* Modelled on the DataManager more or less.
*
* TODO Add some tests.
* TODO Lock down user info access programmatically. Users can only get usernames?
*
* @author AnJackson
*
*/
@Stateless(mappedName="security/LocalUserManager")
@Local(UserManager.class)
@Remote(UserManager.class)
@LocalBinding(jndiBinding="planets-project.eu/UserManager/local")
@RemoteBinding(jndiBinding="planets-project.eu/UserManager/remote")
@SecurityDomain("PlanetsRealm")
public class UserManagerImpl implements UserManager {
  private static Logger log = Logger.getLogger(UserManagerImpl.class.getName());

  /**
   * This is the JPA entity manager declaration.
   */
  @PersistenceContext(unitName="planetsAdmin", type=PersistenceContextType.TRANSACTION)
  private EntityManager manager;

  /**
   * This hooks into the EJB Context.
   */
  @Resource SessionContext ctx;

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#getUser(java.lang.Long)
   */
  @RolesAllowed( { "user" })
  public User getUser(Long userId) {
    return manager.find(UserImpl.class, userId);
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#isUsernameAvailable(java.lang.String)
   */
  @PermitAll
  public boolean isUsernameAvailable(String username) {
    log.info("Checking availability of " + username + " in user manager");
    try {
      log.info("Who you gonna call, getUserByUsername for " + username);
      User user = getUserByUsername(username);
      log.info("Checking for null username");
      if( getUserByUsername(username) != null ) {
        log.info("Found a user :" + user.getUsername());
        log.info("username " + username + " NOT available");
        return false;
      } else {
        log.info("username " + username + " available");
        return true;
      }
    } catch (UserNotFoundException e) {
      // This is fine, if the user isn't found then it's available
      log.info("UserNotFoundException so returning true");
      return true;
    }
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#getUsers()
   */
  @RolesAllowed( { "user" })
  @SuppressWarnings("unchecked")
  public List<User> getUsers() {
    Query query = manager.createQuery("from UserImpl");
    return (List<User>) query.getResultList();
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#getUsernames()
   */
  @RolesAllowed( { "user" })
  public List<String> getUsernames() {
    List<User> users = this.getUsers();
    List<String> usernames = new ArrayList<String>(users.size());
    for( User user : users ) usernames.add(user.getUsername());
    return usernames;
  }


  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#getUserByUsername(java.lang.String)
   */
  @RolesAllowed( { "user" })
  public User getUserByUsername(String username) throws UserNotFoundException {
    log.info("UserManagerImpl.getUserByUsername()");
    // Test programmatic some security stuff:
    log.info("Attempting some security realm lookups : java:comp/env/security/subject.");
    try {
      log.info("Getting an intital context");
      InitialContext ic = new InitialContext();
      log.info("performing subject lookup");
      Subject subject = (Subject)ic.lookup("java:comp/env/security/subject");
      log.info("listing principles");
      // To list the Principals contained in the Subject...
      for( Principal p : subject.getPrincipals() ) {
        log.info("Principal (" + p.getClass().getName()
            + ") : " + p.getName());
      }
      // To get the roles (the instance of java.security.acl.Group
      // in the list of Principals)
      log.info("going for the roles now");
      Iterator<Group> groups = subject.getPrincipals(java.security.acl.Group.class).iterator();
      if (groups.hasNext()) {
        log.info("getting role groups");
        Group roles = (Group)groups.next();
        Enumeration<?> roleEnum = roles.members();
        while (roleEnum.hasMoreElements()) {
          log.info("Role:  " + roleEnum.nextElement());
        }
      }
    } catch ( javax.naming.NamingException e ) {
      log.info("Java naming problem");
      log.info(e.getMessage());
    }

    // Now perform the actual getUserByUsername operation:
    log.info("creating query");
    Query query = manager.createQuery("SELECT u FROM UserImpl AS u WHERE u.username =:username");
    log.info("setting parameter username to " + username);
    query.setParameter("username", username);
    log.info("query.getsingleresult()");
    // Doing this slightly differently due to runtime exception when no result
    User user = null;
    try {
      log.info("In catch block to retrieve user");
      user = (User)query.getSingleResult();
    } catch (NoResultException e) {
      // Catch the runtime exception and set user to null
      log.info("User doesn't exist so setting to null");
      user = null;
    }
    log.info("testing for user == null");
    if( user == null ) throw new UserNotFoundException();
    log.info("User ID = " + user.getId().toString());
    log.info("User name = " + user.getUsername());
    return user;
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#addUser(eu.planets_project.ifr.core.security.api.model.User)
   */
  @RolesAllowed( { "admin" })
  public void addUser(User user) throws UserNotValidException {
    log.info("UserManagerImpl.addUser()");
    log.info("User name = " + user.getUsername());
    if (null != user.getId()) {
      log.info("User ID = " + user.getId().toString());
    }
    if( ! isUsernameAvailable(user.getUsername()))
      throw new UserNotValidException();
    // Should be okay to store:
    manager.persist(user);
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#removeUser(java.lang.Long)
   */
  @RolesAllowed( { "admin" })
  public void removeUser(Long userId) {
    manager.remove(this.getUser(userId));
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#saveUser(eu.planets_project.ifr.core.security.api.model.User)
   */
  @RolesAllowed( { "user" })
  public void saveUser(User user) {
    Principal caller = ctx.getCallerPrincipal();
    log.info("User "+caller.getName()+" is attempting to save User("+user.getUsername()+")");
    if( ctx.isCallerInRole("admin") ||
        caller.getName().equals(user.getUsername()) ) {
      log.info("User "+caller.getName()+" saved User("+user.getUsername()+")");
      manager.merge(user);
    } else {
      log.warning("User "+caller.getName()+" attempted to save User("+user.getUsername()+")");
    }
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#sendUserMessage(java.lang.String, java.lang.String, java.lang.String)
   */
  @RolesAllowed( { "user" })
  public void sendUserMessage(String username, String subject, String body) {
    // Lookup the user:
    User user = null;
    try {
      user = this.getUserByUsername(username);
    } catch (UserNotFoundException e) {
      log.info("UserNotFoundException");
      log.warning(e.getMessage());
      return;
    }

    // Send them a message.
    PlanetsMailMessage mailer = new PlanetsMailMessage();
    mailer.setSubject(subject);
    mailer.setBody(body);
    mailer.addRecipient(user.getEmail());
    mailer.send();
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#assignRoleToUser(eu.planets_project.ifr.core.security.api.model.User, java.lang.String)
   */
  @RolesAllowed( { "admin", "testbed.admin" })
  public void assignRoleToUser(User user, String role) {
    user.addRole(new RoleImpl(role));
    saveUser(user);
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#listRoles()
   */
  @PermitAll
  @SuppressWarnings("unchecked")
  public String[] listRoles() {
    Query query = manager.createQuery("from RoleImpl");
    List<Role> roles = (List<Role>) query.getResultList();
    String[] rolestr = new String[roles.size()];
    int index = 0;
    for (Role role : roles) {
      rolestr[index++] = role.getName();
    }
    return rolestr;
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#listUsersInRole(java.lang.String)
   */
  @RolesAllowed( { "user" })
  public List<User> listUsersInRole(String role) {
    // TODO This should list the users by role at the DB level, not filter the all-user list.
    /*
        Query query = manager.createQuery("FROM User AS u, Role as r INNER JOIN u.role == r.id WHERE r.name == :role");
        query.setParameter("role", role);
        return (List<UserImpl>) query.getResultList();
     */
    ArrayList<User> roleUsers = new ArrayList<User>();
    for( User user : this.getUsers() ) {
      for( Role urole : user.getRoles()) {
        if( urole.getName().equals(role))
          roleUsers.add(user);
      }
    }
    return roleUsers;
  }

  /**
   * {@inheritDoc}
   * @see eu.planets_project.ifr.core.security.api.services.UserManager#revokeRoleFromUser(eu.planets_project.ifr.core.security.api.model.User, java.lang.String)
   */
  @RolesAllowed( { "admin", "testbed.admin" })
  public void revokeRoleFromUser(User user, String role) {
    user.removeRole(new RoleImpl(role));
    saveUser(user);
  }

  /**
   * Hook up to an instance of the Planets User Manager.
   * @return A UserManager, as discovered via JNDI.
   */
  public static UserManager getPlanetsUserManager() {
    try{
      Context jndiContext = new javax.naming.InitialContext();
      UserManager um = (UserManager) PortableRemoteObject.narrow(
          jndiContext.lookup("planets-project.eu/UserManager/remote"), UserManager.class);
      return um;
    }catch (NamingException e) {
      log.severe("Failure during lookup of the UserManager PortableRemoteObject: "+e.toString());
      return null;
    }
  }

}
TOP

Related Classes of eu.planets_project.ifr.core.security.impl.services.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.