Package ch.entwine.weblounge.common.impl.security

Source Code of ch.entwine.weblounge.common.impl.security.WebloungeUserImpl

/*
*  Weblounge: Web Content Management System
*  Copyright (c) 2003 - 2011 The Weblounge Team
*  http://entwinemedia.com/weblounge
*
*  This program is free software; you can redistribute it and/or
*  modify it under the terms of the GNU Lesser General Public License
*  as published by the Free Software Foundation; either version 2
*  of the License, or (at your option) any later version.
*
*  This program is distributed in the hope that it will be useful,
*  but WITHOUT ANY WARRANTY; without even the implied warranty of
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*  GNU Lesser General Public License for more details.
*
*  You should have received a copy of the GNU Lesser General Public License
*  along with this program; if not, write to the Free Software Foundation
*  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package ch.entwine.weblounge.common.impl.security;

import ch.entwine.weblounge.common.impl.language.LanguageUtils;
import ch.entwine.weblounge.common.impl.util.WebloungeDateFormat;
import ch.entwine.weblounge.common.impl.util.config.ConfigurationUtils;
import ch.entwine.weblounge.common.impl.util.xml.XPathHelper;
import ch.entwine.weblounge.common.language.Language;
import ch.entwine.weblounge.common.security.DigestType;
import ch.entwine.weblounge.common.security.Password;
import ch.entwine.weblounge.common.security.Role;
import ch.entwine.weblounge.common.security.WebloungeUser;
import ch.entwine.weblounge.common.site.Site;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathFactory;

/**
* Default implementation of a weblounge user.
*/
public class WebloungeUserImpl extends UserImpl implements WebloungeUser {

  /** Logging facility */
  private static final Logger logger = LoggerFactory.getLogger(WebloungeUserImpl.class);

  /** Enabled flag */
  protected boolean enabled = true;

  /** First name of the person */
  protected String firstName = null;

  /** Family name of the person */
  protected String lastName = null;

  /** E-mail address */
  protected String email = null;

  /** Preferred language */
  protected Language language = null;

  /** Cached initials */
  private String initials = null;

  /** Password challenge */
  protected String challenge = null;

  /** Password challenge response */
  protected byte[] response = null;

  /** Password hash type, either plain or md5 */
  protected DigestType responseDigestType = DigestType.plain;

  /** Additional properties of this user */
  protected Map<String, Object> properties = new HashMap<String, Object>();

  /** Date of the last login */
  protected Date lastLogin = null;

  /** Source of the last login */
  protected String lastLoginSource = null;

  /** Cached version of automatically generated initials */
  private String cachedInitials = null;

  /** Cached version of automatically generated name */
  private String cachedName = null;

  /**
   * Creates a user with the given login and initializes it from the weblounge
   * database.
   *
   * @param login
   *          the username
   * @param realm
   *          the login domain
   */
  public WebloungeUserImpl(String login, String realm) {
    super(login, realm);
  }

  /**
   * Creates a user with login <code>login</code> and the default realm
   * {@link #DefaultRealm}.
   *
   * @param login
   *          the username
   */
  public WebloungeUserImpl(String login) {
    this(login, DefaultRealm);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#isEnabled()
   */
  public boolean isEnabled() {
    return enabled;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#canLogin()
   */
  public boolean canLogin() {
    Set<Object> passwords = getPrivateCredentials(Password.class);
    return isEnabled() && passwords.size() > 0;
  }

  /**
   * Sets the enabled flag. Set it to <code>true</code> to enable the login.
   *
   * @param enabled
   *          <code>true</code> to enable this login
   */
  public void setEnabled(boolean enabled) {
    this.enabled = enabled;
  }

  /**
   * Sets this person's first name.
   *
   * @param firstname
   *          the first name
   */
  public void setFirstName(String firstname) {
    this.firstName = firstname;
    cachedInitials = null;
    cachedName = null;
  }

  /**
   * Returns the first name of this person.
   *
   * @return the person's first name
   */
  public String getFirstName() {
    return firstName;
  }

  /**
   * Sets this person's last name.
   *
   * @param lastname
   *          the last name
   */
  public void setLastName(String lastname) {
    this.lastName = lastname;
    cachedInitials = null;
    cachedName = null;
  }

  /**
   * Returns the last name of this person.
   *
   * @return the person's last name
   */
  public String getLastName() {
    return lastName;
  }

  /**
   * Returns the name of this user. If possible, the value returned consists of
   * type <first name><last name>.
   *
   * @returns the full user name
   */
  public String getName() {
    if (name != null)
      return name;
    if (cachedName != null)
      return cachedName;

    String first = getFirstName();
    String last = getLastName();
    if (StringUtils.trimToNull(first) == null && StringUtils.trimToNull(last) == null)
      return null;

    // Create the name
    StringBuffer name = new StringBuffer();
    if (StringUtils.trimToNull(first) != null) {
      name.append(first);
    }
    if (StringUtils.trimToNull(last) != null) {
      if (name.length() > 0)
        name.append(" ");
      name.append(last);
    }

    // Cache for further reference
    cachedName = name.toString();
    return cachedName;
  }

  /**
   * Sets the person's email.
   *
   * @param email
   *          the email address
   */
  public void setEmail(String email) {
    this.email = email;
  }

  /**
   * Returns the email address of this person.
   *
   * @return the person's email address
   */
  public String getEmail() {
    return email;
  }

  /**
   * Sets the person's preferred language.
   *
   * @param language
   *          the preferred language
   */
  public void setLanguage(Language language) {
    this.language = language;
  }

  /**
   * Returns the preferred language of this person.
   *
   * @return the person's preferred language
   */
  public Language getLanguage() {
    return language;
  }

  /**
   * Returns the short version of the persons name, which are constructed from
   * the first and the last name of the user.
   *
   * @return the persons initials
   */
  public String getInitials() {
    if (initials != null)
      return initials;
    if (cachedInitials != null)
      return cachedInitials;
    StringBuffer initials = new StringBuffer();
    String first = getFirstName();
    String last = getLastName();
    if (!StringUtils.isBlank(first) && !StringUtils.isBlank(last)) {
      initials.append(first.substring(0, 1));
      initials.append(last.subSequence(0, 1));
      cachedInitials = initials.toString().toLowerCase();
      return cachedInitials;
    }
    return null;
  }

  /**
   * Sets the person's initials.
   *
   * @param initials
   *          the person's initials
   */
  public void setInitials(String initials) {
    this.initials = initials;
  }

  /**
   * Sets the last login date.
   *
   * @param date
   *          the login date
   * @param src
   *          the login source
   */
  public void setLastLogin(Date date, String src) {
    lastLogin = date;
    lastLoginSource = src;
  }

  /**
   * Returns the data where the user logged in for the last time.
   *
   * @return the last login
   */
  public Date getLastLogin() {
    return lastLogin;
  }

  /**
   * Returns the last login source. The source can be either an ip address or a
   * host name.
   *
   * @return the source of the last login
   */
  public String getLastLoginFrom() {
    return lastLoginSource;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#getChallenge()
   */
  @Override
  public String getChallenge() {
    return challenge;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#setChallenge(java.lang.String)
   */
  @Override
  public void setChallenge(String challenge) {
    this.challenge = challenge;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#getResponse()
   */
  @Override
  public byte[] getResponse() {
    return response;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#setResponse(java.lang.String)
   */
  @Override
  public void setResponse(byte[] response, DigestType digest) {
    this.response = response;
    this.responseDigestType = digest;
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#getProperty(java.lang.String)
   */
  public Object getProperty(String name) {
    return properties.get(name);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#removeProperty(java.lang.String)
   */
  public Object removeProperty(String name) {
    return properties.remove(name);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.security.WebloungeUser#setProperty(java.lang.String,
   *      java.lang.Object)
   */
  public void setProperty(String name, Object value) {
    properties.put(name, value);
  }

  /**
   * Initializes this user object by reading all information from the
   * <code>XML</code> configuration node.
   *
   * @param userNode
   *          the <code>XML</code> node containing the user configuration
   * @param site
   *          the associated site
   */
  public static WebloungeUserImpl fromXml(Node userNode, Site site)
      throws IllegalStateException {
    XPath xpath = XPathFactory.newInstance().newXPath();
    return fromXml(userNode, site, xpath);
  }

  /**
   * Initializes this user object by reading all information from the
   * <code>XML</code> configuration node.
   *
   * @param userNode
   *          the <code>XML</code> node containing the user configuration
   * @param site
   *          the associated site
   * @param xpath
   *          the {@link XPath} processor
   */
  public static WebloungeUserImpl fromXml(Node userNode, Site site, XPath xpath)
      throws IllegalStateException {

    if (userNode == null)
      return null;

    String login = XPathHelper.valueOf(userNode, "@id", xpath);
    WebloungeUserImpl user = new WebloungeUserImpl(login);

    String realm = XPathHelper.valueOf(userNode, "@realm", xpath);
    if (realm != null)
      user.realm = realm;
    user.enabled = ConfigurationUtils.isTrue(XPathHelper.valueOf(userNode, "@enabled", xpath));
    String name = XPathHelper.valueOf(userNode, "profile/name", xpath);
    if (name != null) {
      user.name = XPathHelper.valueOf(userNode, "profile/name", xpath);
    } else {
      user.firstName = XPathHelper.valueOf(userNode, "profile/firstname", xpath);
      user.lastName = XPathHelper.valueOf(userNode, "profile/lastname", xpath);
    }
    user.initials = XPathHelper.valueOf(userNode, "profile/initials", xpath);
    user.email = XPathHelper.valueOf(userNode, "profile/email", xpath);
    String language = XPathHelper.valueOf(userNode, "profile/language", xpath);
    if (language != null) {
      Language l = LanguageUtils.getLanguage(language);
      user.language = (l != null) ? l : site.getDefaultLanguage();
    }

    // Password
    String password = XPathHelper.valueOf(userNode, "security/password", xpath);
    if (password != null) {
      String digestType = null;
      try {
        digestType = XPathHelper.valueOf(userNode, "security/password/@type", xpath);
        Password pw = new PasswordImpl(password, DigestType.valueOf(digestType));
        user.addPrivateCredentials(pw);
      } catch (Throwable t) {
        throw new IllegalStateException("Unknown password digest found: " + digestType);
      }
    }

    // Challenge / Response
    user.challenge = XPathHelper.valueOf(userNode, "security/challenge", xpath);
    String response = XPathHelper.valueOf(userNode, "security/response", xpath);
    if (response != null) {
      String digestType = null;
      try {
        digestType = XPathHelper.valueOf(userNode, "security/response/@type", xpath);
        user.responseDigestType = DigestType.valueOf(digestType);
        user.response = response.getBytes();
      } catch (Throwable t) {
        throw new IllegalStateException("Unknown response digest found: " + digestType);
      }
    }

    // Last login
    String lastLogin = XPathHelper.valueOf(userNode, "security/lastlogin/date", xpath);
    try {
      if (lastLogin != null)
        user.lastLogin = WebloungeDateFormat.parseStatic(lastLogin);
      user.lastLoginSource = XPathHelper.valueOf(userNode, "security/lastlogin/ip", xpath);
    } catch (ParseException e) {
      // It's not important. Let's log and then forget about it
      logger.error("Unable to parse last login date '{}'", lastLogin, e);
    }

    // Properties
    NodeList properties = XPathHelper.selectList(userNode, "properties/property", xpath);
    if (properties != null) {
      for (int i = 0; i < properties.getLength(); i++) {
        String key = XPathHelper.valueOf(properties.item(i), "name", xpath);
        String value = XPathHelper.valueOf(properties.item(i), "value", xpath);
        // TODO: Check for serialized objects or xml nodes
        if (key != null && value != null)
          user.properties.put(key, value);
      }
    }

    return user;
  }

  /**
   * Returns an <code>XML</code> representation of this user.
   *
   * @return the user as an <code>XML</code> document fragment
   */
  public String toXml() {
    StringBuffer b = new StringBuffer();

    // Add root node
    b.append("<user id=\"" + login + "\"");
    if (realm != null) {
      b.append(" realm=\"");
      b.append(realm);
      b.append("\"");
    }
    b.append(" enabled=\"" + enabled + "\"");
    b.append(">");

    //
    // Profile
    //

    b.append("<profile>");

    // First name
    if (firstName != null) {
      b.append("<firstname><![CDATA[");
      b.append(firstName);
      b.append("]]></firstname>");
    }

    // Last name
    if (lastName != null) {
      b.append("<lastname><![CDATA[");
      b.append(lastName);
      b.append("]]></lastname>");
    }

    // Name, if first name and last name were not given
    if (name != null && firstName == null && lastName == null) {
      b.append("<name><![CDATA[");
      b.append(name);
      b.append("]]></name>");
    }

    // Initials
    if (getInitials() != null) {
      b.append("<initials><![CDATA[");
      b.append(getInitials());
      b.append("]]></initials>");
    }

    // Email
    if (email != null) {
      b.append("<email>");
      b.append(email);
      b.append("</email>");
    }

    // Language
    if (language != null) {
      b.append("<language>");
      b.append(language.getIdentifier());
      b.append("</language>");
    }

    b.append("</profile>");

    //
    // Security
    //

    b.append("<security>");

    // Password
    Set<Object> passwords = getPrivateCredentials(Password.class);
    for (Object o : passwords) {
      Password password = (Password) o;
      b.append("<password type=\"");
      b.append(password.getDigestType().toString());
      b.append("\"><![CDATA[");
      b.append(password.getPassword());
      b.append("]]></password>");
    }

    // Roles
    Set<Object> roles = getPublicCredentials(Role.class);
    for (Object r : roles) {
      Role role = (Role) r;
      b.append("<role context=\"");
      b.append(role.getContext());
      b.append("\"><![CDATA[");
      b.append(role.getName());
      b.append("]]></password>");
    }

    // challenge - response
    if (challenge != null) {
      b.append("<challenge><![CDATA[");
      b.append(challenge);
      b.append("]]></challenge>");
    }

    if (response != null) {
      b.append("<response type=\"");
      b.append(responseDigestType.toString());
      b.append("\"><![CDATA[");
      b.append(new String(response));
      b.append("]]></response>");
    }

    // Last login
    if (lastLogin != null && lastLoginSource != null) {
      b.append("<lastlogin>");
      b.append("<date>");
      b.append(WebloungeDateFormat.formatStatic(lastLogin));
      b.append("</date>");
      b.append("<ip>");
      b.append(lastLoginSource);
      b.append("</ip>");
      b.append("</lastlogin>");
    }

    b.append("</security>");

    // properties
    if (properties != null && properties.size() > 0) {
      b.append("<properties>");
      for (Map.Entry<String, Object> entry : properties.entrySet()) {
        b.append("<property>");
        b.append("<name>");
        b.append(entry.getKey());
        b.append("</name>");
        b.append("<value><![CDATA[");
        // TODO: Examine object. If XML node or serializable, serialize with
        // care
        b.append(entry.getValue().toString());
        b.append("]]></value>");
        b.append("</property>");
      }
      b.append("</properties>");
    }

    b.append("</user>");
    return b.toString();
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.impl.security.AuthenticatedUserImpl#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    // Overwritten to document that we are using the super impl
    return super.equals(obj);
  }

  /**
   * {@inheritDoc}
   *
   * @see ch.entwine.weblounge.common.impl.security.AuthenticatedUserImpl#hashCode()
   */
  @Override
  public int hashCode() {
    // Overwritten to document that we are using the super impl
    return super.hashCode();
  }

}
TOP

Related Classes of ch.entwine.weblounge.common.impl.security.WebloungeUserImpl

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.