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