    001/*
    002    Licensed to the Apache Software Foundation (ASF) under one
    003    or more contributor license agreements.  See the NOTICE file
    004    distributed with this work for additional information
    005    regarding copyright ownership.  The ASF licenses this file
    006    to you under the Apache License, Version 2.0 (the
    007    "License"); you may not use this file except in compliance
    008    with the License.  You may obtain a copy of the License at
    009
    010       http://www.apache.org/licenses/LICENSE-2.0
    011
    012    Unless required by applicable law or agreed to in writing,
    013    software distributed under the License is distributed on an
    014    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
    015    KIND, either express or implied.  See the License for the
    016    specific language governing permissions and limitations
    017    under the License.
    018 */
    019package org.apache.wiki.auth.user;
    020
    021import org.apache.commons.lang3.StringUtils;
    022
    023import javax.servlet.http.HttpServletRequest;
    024import java.io.Serializable;
    025import java.util.Date;
    026import java.util.HashMap;
    027import java.util.Map;
    028
    029
    030/**
    031 * Default implementation for representing wiki user information, such as the login name, full name, wiki name, and e-mail address.
    032 *
    033 * @since 2.3
    034 */
    035public final class DefaultUserProfile implements UserProfile {
    036
    037    private static final long serialVersionUID = -5600466893735300647L;
    038    private static final String EMPTY_STRING = "";
    039    private static final String WHITESPACE = "\\s";
    040
    041    private final Map< String, Serializable > attributes = new HashMap<>();
    042    private Date created;
    043    private String email;
    044    private String fullname;
    045    private Date lockExpiry;
    046    private String loginName;
    047    private Date modified;
    048    private String password;
    049    private String uid;
    050    private String wikiname;
    051
    052    /**
    053     * Package constructor to allow direct instantiation only from package related classes (i.e., AbstractUserDatabase).
    054     */
    055    DefaultUserProfile() {}
    056
    057    /**
    058     * {@inheritDoc}
    059     */
    060    @Override
    061    public boolean equals( final Object o ) {
    062        if ( o instanceof UserProfile ) {
    063            final DefaultUserProfile u = ( DefaultUserProfile )o;
    064            return  same( fullname, u.fullname ) &&
    065                    same( password, u.password ) &&
    066                    same( loginName, u.loginName ) &&
    067                    same( StringUtils.lowerCase( email ), StringUtils.lowerCase( u.email ) ) &&
    068                    same( wikiname, u.wikiname );
    069        }
    070
    071        return false;
    072    }
    073
    074    @Override
    075    public int hashCode() {
    076        return ( fullname  != null ? fullname.hashCode()  : 0 ) ^
    077               ( password  != null ? password.hashCode()  : 0 ) ^
    078               ( loginName != null ? loginName.hashCode() : 0 ) ^
    079               ( wikiname  != null ? wikiname.hashCode()  : 0 ) ^
    080               ( email     != null ? StringUtils.lowerCase( email ).hashCode() : 0 );
    081    }
    082
    083    /**
    084     * Returns the creation date
    085     *
    086     * @return the creation date
    087     * @see org.apache.wiki.auth.user.UserProfile#getCreated()
    088     */
    089    @Override
    090    public Date getCreated()
    091    {
    092        return created;
    093    }
    094
    095    /**
    096     * Returns the user's e-mail address.
    097     *
    098     * @return the e-mail address
    099     */
    100    @Override
    101    public String getEmail()
    102    {
    103        return email;
    104    }
    105
    106    /**
    107     * Returns the user's full name.
    108     *
    109     * @return the full name
    110     */
    111    @Override
    112    public String getFullname()
    113    {
    114        return fullname;
    115    }
    116
    117    /**
    118     * Returns the last-modified date.
    119     *
    120     * @return the last-modified date
    121     * @see org.apache.wiki.auth.user.UserProfile#getLastModified()
    122     */
    123    @Override
    124    public Date getLastModified()
    125    {
    126        return modified;
    127    }
    128
    129    /**
    130     * Returns the user's login name.
    131     * @return the login name
    132     */
    133    @Override
    134    public String getLoginName()
    135    {
    136        return loginName;
    137    }
    138
    139    /**
    140     * Returns the user password for use with custom authentication. Note that the password field is not meaningful for container
    141     * authentication; the user's private credentials are generally stored elsewhere. While it depends on the {@link UserDatabase}
    142     * implementation, in most cases the value returned by this method will be a password hash, not the password itself.
    143     *
    144     * @return the password
    145     */
    146    @Override
    147    public String getPassword()
    148    {
    149        return password;
    150    }
    151
    152    /**
    153     * Returns the user's wiki name.
    154     *
    155     * @return the wiki name.
    156     */
    157    @Override
    158    public String getWikiName()
    159    {
    160        return wikiname;
    161    }
    162
    163    /**
    164     * Returns <code>true</code> if the user profile is new. This implementation checks whether {@link #getLastModified()} returns
    165     * <code>null</code> to determine the status.
    166     *
    167     * @see org.apache.wiki.auth.user.UserProfile#isNew()
    168     */
    169    @Override
    170    public boolean isNew()
    171    {
    172        return  modified == null;
    173    }
    174
    175    /**
    176     * @param date the creation date
    177     * @see org.apache.wiki.auth.user.UserProfile#setCreated(java.util.Date)
    178     */
    179    @Override
    180    public void setCreated( final Date date )
    181    {
    182        created = date;
    183    }
    184
    185    /**
    186     * Sets the user's e-mail address.
    187     *
    188     * @param email the e-mail address
    189     */
    190    @Override
    191    public void setEmail( final String email )
    192    {
    193        this.email = email;
    194    }
    195
    196    /**
    197     * Sets the user's full name. For example, "Janne Jalkanen."
    198     *
    199     * @param arg the full name
    200     */
    201    @Override
    202    public void setFullname( final String arg ) {
    203        fullname = arg;
    204
    205        // Compute wiki name
    206        if ( fullname != null ) {
    207            wikiname = fullname.replaceAll( WHITESPACE, EMPTY_STRING );
    208        }
    209    }
    210
    211    /**
    212     * Sets the last-modified date.
    213     *
    214     * @param date the last-modified date
    215     * @see org.apache.wiki.auth.user.UserProfile#setLastModified(java.util.Date)
    216     */
    217    @Override
    218    public void setLastModified( final Date date )
    219    {
    220        modified = date;
    221    }
    222
    223    /**
    224     * Sets the name by which the user logs in. The login name is used as the username for custom authentication (see
    225     * {@link org.apache.wiki.auth.AuthenticationManager#login(org.apache.wiki.api.core.Session,HttpServletRequest, String, String)}).
    226     * The login name is typically a short name ("jannej"). In contrast, the wiki name is typically of type
    227     * FirstnameLastName ("JanneJalkanen").
    228     *
    229     * @param name the login name
    230     */
    231    @Override
    232    public void setLoginName( final String name )
    233    {
    234        loginName = name;
    235    }
    236
    237    /**
    238     * Sets the user's password for use with custom authentication. It is <em>not</em> the responsibility of implementing classes to hash
    239     * the password; that responsibility is borne by the UserDatabase implementation during save operations (see
    240     * {@link UserDatabase#save(UserProfile)}). Note that the password field is not meaningful for container authentication; the user's
    241     * private credentials are generally stored elsewhere.
    242     *
    243     * @param arg the password
    244     */
    245    @Override
    246    public void setPassword( final String arg )
    247    {
    248        password = arg;
    249    }
    250
    251    /**
    252     * Returns a string representation of this user profile.
    253     *
    254     * @return the string
    255     */
    256    @Override
    257    public String toString()
    258    {
    259        return "[DefaultUserProfile: '" + getFullname() + "']";
    260    }
    261
    262    /**
    263     * Private method that compares two objects and determines whether they are equal. Two nulls are considered equal.
    264     *
    265     * @param arg1 the first object
    266     * @param arg2 the second object
    267     * @return the result of the comparison
    268     */
    269    private boolean same( final Object arg1, final Object arg2 ) {
    270        if( arg1 == null && arg2 == null ) {
    271            return true;
    272        }
    273        if( arg1 == null || arg2 == null ) {
    274            return false;
    275        }
    276        return arg1.equals( arg2 );
    277    }
    278
    279    //--------------------------- Attribute and lock interface implementations ---------------------------
    280
    281    /**
    282     * {@inheritDoc}
    283     */
    284    @Override
    285    public Map< String, Serializable > getAttributes()
    286    {
    287        return attributes;
    288    }
    289
    290    /**
    291     * {@inheritDoc}
    292     */
    293    @Override
    294    public Date getLockExpiry()
    295    {
    296        return isLocked() ? lockExpiry : null;
    297    }
    298
    299    /**
    300     * {@inheritDoc}
    301     */
    302    @Override
    303    public String getUid()
    304    {
    305        return uid;
    306    }
    307
    308    /**
    309     * {@inheritDoc}
    310     */
    311    @Override
    312    public boolean isLocked() {
    313        final boolean locked = lockExpiry != null && System.currentTimeMillis() < lockExpiry.getTime();
    314        // Clear the lock if it's expired already
    315        if( !locked && lockExpiry != null ) {
    316            lockExpiry = null;
    317        }
    318        return locked;
    319
    320    }
    321
    322    /**
    323     * {@inheritDoc}
    324     */
    325    @Override
    326    public void setLockExpiry( final Date expiry )
    327    {
    328        this.lockExpiry = expiry;
    329    }
    330
    331    /**
    332     * {@inheritDoc}
    333     */
    334    @Override
    335    public void setUid( final String uid )
    336    {
    337        this.uid = uid;
    338    }
    339
    340}