001package org.apache.turbine.services.security;
002
003
004/*
005 * Licensed to the Apache Software Foundation (ASF) under one
006 * or more contributor license agreements.  See the NOTICE file
007 * distributed with this work for additional information
008 * regarding copyright ownership.  The ASF licenses this file
009 * to you under the Apache License, Version 2.0 (the
010 * "License"); you may not use this file except in compliance
011 * with the License.  You may obtain a copy of the License at
012 *
013 *   http://www.apache.org/licenses/LICENSE-2.0
014 *
015 * Unless required by applicable law or agreed to in writing,
016 * software distributed under the License is distributed on an
017 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
018 * KIND, either express or implied.  See the License for the
019 * specific language governing permissions and limitations
020 * under the License.
021 */
022
023
024import java.util.ArrayList;
025import java.util.List;
026
027import org.apache.commons.configuration.Configuration;
028import org.apache.fulcrum.security.acl.AccessControlList;
029import org.apache.fulcrum.security.model.turbine.TurbineUserManager;
030import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
031import org.apache.fulcrum.security.util.DataBackendException;
032import org.apache.fulcrum.security.util.EntityExistsException;
033import org.apache.fulcrum.security.util.PasswordMismatchException;
034import org.apache.fulcrum.security.util.UnknownEntityException;
035import org.apache.fulcrum.security.util.UserSet;
036import org.apache.turbine.om.security.DefaultUserImpl;
037import org.apache.turbine.om.security.User;
038import org.apache.turbine.services.ServiceManager;
039import org.apache.turbine.services.TurbineServices;
040import org.apache.turbine.util.ObjectUtils;
041
042/**
043 * Default user manager.
044 *
045 * The user manager wraps Fulcrum security user objects into
046 * Turbine-specific ones.
047 *
048 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
049 * @version $Id: PassiveUserManager.java 1096130 2011-04-23 10:37:19Z ludwig $
050 */
051public class DefaultUserManager implements UserManager
052{
053    /** Fulcrum user manager instance to delegate to */
054    private TurbineUserManager umDelegate = null;
055
056    /**
057     * Wrap a Fulcrum user object into a Turbine user object
058     *
059     * @param user the user object to delegate to
060     *
061     * @return the wrapped object
062     */
063    protected <U extends User> U wrap(TurbineUser user)
064    {
065        @SuppressWarnings("unchecked")
066        U u = (U)new DefaultUserImpl(user);
067        return u;
068    }
069
070    /**
071     * Initializes the UserManager
072     *
073     * @param conf A Configuration object to init this Manager
074     */
075    @Override
076    public void init(Configuration conf)
077    {
078        ServiceManager manager = TurbineServices.getInstance();
079        this.umDelegate = (TurbineUserManager)manager.getService(TurbineUserManager.ROLE);
080    }
081
082    /**
083     * Check whether a specified user's account exists.
084     *
085     * The login name is used for looking up the account.
086     *
087     * @param user The user to be checked.
088     * @return true if the specified account exists
089     * @throws DataBackendException if there was an error accessing the data backend.
090     */
091    @Override
092    public boolean accountExists(User user)
093            throws DataBackendException
094    {
095        return umDelegate.checkExists(user);
096    }
097
098    /**
099     * Check whether a specified user's account exists.
100     *
101     * The login name is used for looking up the account.
102     *
103     * @param userName The name of the user to be checked.
104     * @return true if the specified account exists
105     * @throws DataBackendException if there was an error accessing the data backend.
106     */
107    @Override
108    public boolean accountExists(String userName)
109            throws DataBackendException
110    {
111        return umDelegate.checkExists(userName);
112    }
113
114    /**
115     * Retrieve a user from persistent storage using username as the
116     * key.
117     *
118     * @param username the name of the user.
119     * @return an User object.
120     * @exception UnknownEntityException if the user's record does not
121     *            exist in the database.
122     * @exception DataBackendException if there is a problem accessing the
123     *            storage.
124     */
125    @Override
126    public <U extends User> U retrieve(String username)
127            throws UnknownEntityException, DataBackendException
128    {
129        TurbineUser u = umDelegate.getUser(username);
130        return wrap(u);
131    }
132
133    /**
134     * Retrieve a set of users that meet the specified criteria.
135     *
136     * As the keys for the criteria, you should use the constants that
137     * are defined in {@link User} interface, plus the names
138     * of the custom attributes you added to your user representation
139     * in the data storage. Use verbatim names of the attributes -
140     * without table name prefix in case of DB implementation.
141     *
142     * @param criteria The criteria of selection.
143     * @return a List of users meeting the criteria.
144     * @throws DataBackendException if there is a problem accessing the
145     *         storage.
146     */
147    @Override
148    public List<? extends User> retrieveList(Object criteria)
149            throws DataBackendException
150    {
151        UserSet uset = umDelegate.getAllUsers();
152        List<User> userList = new ArrayList<User>();
153
154        for (org.apache.fulcrum.security.entity.User u : uset)
155        {
156            TurbineUser tu = (TurbineUser)u;
157            userList.add(wrap(tu));
158        }
159
160        return userList;
161    }
162
163    /**
164     * Retrieve a user from persistent storage using username as the
165     * key, and authenticate the user. The implementation may chose
166     * to authenticate to the server as the user whose data is being
167     * retrieved.
168     *
169     * @param username the name of the user.
170     * @param password the user supplied password.
171     * @return an User object.
172     * @exception PasswordMismatchException if the supplied password was
173     *            incorrect.
174     * @exception UnknownEntityException if the user's record does not
175     *            exist in the database.
176     * @exception DataBackendException if there is a problem accessing the
177     *            storage.
178     */
179    @Override
180    public <U extends User> U retrieve(String username, String password)
181            throws PasswordMismatchException, UnknownEntityException,
182            DataBackendException
183    {
184        TurbineUser u = umDelegate.getUser(username, password);
185        return wrap(u);
186    }
187
188    /**
189     * Save an User object to persistent storage. User's record is
190     * required to exist in the storage.
191     *
192     * @param user an User object to store.
193     * @exception UnknownEntityException if the user's record does not
194     *            exist in the database.
195     * @exception DataBackendException if there is a problem accessing the
196     *            storage.
197     */
198    @Override
199    public void store(User user)
200            throws UnknownEntityException, DataBackendException
201    {
202        try
203        {
204            user.setObjectdata(ObjectUtils.serializeMap(user.getPermStorage()));
205        }
206        catch (Exception e)
207        {
208            throw new DataBackendException("Could not serialize permanent storage", e);
209        }
210
211        umDelegate.saveUser(((DefaultUserImpl)user).getUserDelegate());
212    }
213
214    /**
215     * Saves User data when the session is unbound. The user account is required
216     * to exist in the storage.
217     *
218     * LastLogin, AccessCounter, persistent pull tools, and any data stored
219     * in the permData hashtable that is not mapped to a column will be saved.
220     *
221     * @exception UnknownEntityException if the user's account does not
222     *            exist in the database.
223     * @exception DataBackendException if there is a problem accessing the
224     *            storage.
225     */
226    @Override
227    public void saveOnSessionUnbind(User user)
228            throws UnknownEntityException, DataBackendException
229    {
230        store(user);
231    }
232
233    /**
234     * Authenticate an User with the specified password. If authentication
235     * is successful the method returns nothing. If there are any problems,
236     * exception was thrown.
237     *
238     * @param user an User object to authenticate.
239     * @param password the user supplied password.
240     * @exception PasswordMismatchException if the supplied password was
241     *            incorrect.
242     * @exception UnknownEntityException if the user's record does not
243     *            exist in the database.
244     * @exception DataBackendException if there is a problem accessing the
245     *            storage.
246     */
247    @Override
248    public void authenticate(User user, String password)
249            throws PasswordMismatchException, UnknownEntityException,
250            DataBackendException
251    {
252        umDelegate.authenticate(user, password);
253    }
254
255    /**
256     * Creates new user account with specified attributes.
257     *
258     * @param user the object describing account to be created.
259     * @param initialPassword The password to use for the object creation
260     *
261     * @throws DataBackendException if there was an error accessing the data backend.
262     * @throws EntityExistsException if the user account already exists.
263     */
264    @Override
265    public void createAccount(User user, String initialPassword)
266            throws EntityExistsException, DataBackendException
267    {
268        umDelegate.addUser(user, initialPassword);
269    }
270
271    /**
272     * Removes an user account from the system.
273     *
274     * @param user the object describing the account to be removed.
275     * @throws DataBackendException if there was an error accessing the data backend.
276     * @throws UnknownEntityException if the user account is not present.
277     */
278    @Override
279    public void removeAccount(User user)
280            throws UnknownEntityException, DataBackendException
281    {
282        umDelegate.removeUser(user);
283    }
284
285    /**
286     * Change the password for an User.
287     *
288     * @param user an User to change password for.
289     * @param oldPassword the current password supplied by the user.
290     * @param newPassword the current password requested by the user.
291     * @exception PasswordMismatchException if the supplied password was
292     *            incorrect.
293     * @exception UnknownEntityException if the user's record does not
294     *            exist in the database.
295     * @exception DataBackendException if there is a problem accessing the
296     *            storage.
297     */
298    @Override
299    public void changePassword(User user, String oldPassword,
300                               String newPassword)
301            throws PasswordMismatchException, UnknownEntityException,
302            DataBackendException
303    {
304        umDelegate.changePassword(
305                ((DefaultUserImpl)user).getUserDelegate(),
306                oldPassword, newPassword);
307    }
308
309    /**
310     * Forcibly sets new password for an User.
311     *
312     * This is supposed by the administrator to change the forgotten or
313     * compromised passwords. Certain implementations of this feature
314     * would require administrative level access to the authenticating
315     * server / program.
316     *
317     * @param user an User to change password for.
318     * @param password the new password.
319     * @exception UnknownEntityException if the user's record does not
320     *            exist in the database.
321     * @exception DataBackendException if there is a problem accessing the
322     *            storage.
323     */
324    @Override
325    public void forcePassword(User user, String password)
326            throws UnknownEntityException, DataBackendException
327    {
328        umDelegate.forcePassword(user, password);
329    }
330
331    /**
332     * Constructs an User object to represent an anonymous user of the
333     * application.
334     *
335     * @return An anonymous Turbine User.
336     * @throws UnknownEntityException
337     *             if the anonymous User object couldn't be constructed.
338     */
339    @Override
340    public <T extends User> T getAnonymousUser() throws UnknownEntityException
341    {
342        TurbineUser u = umDelegate.getAnonymousUser();
343        return wrap(u);
344    }
345
346    /**
347     * Checks whether a passed user object matches the anonymous user pattern
348     * according to the configured user manager
349     *
350     * @param u a user object
351     *
352     * @return True if this is an anonymous user
353     *
354     */
355    @Override
356    public boolean isAnonymousUser(User u)
357    {
358        return umDelegate.isAnonymousUser(u);
359    }
360
361    /**
362     * Construct a blank User object.
363     *
364     * This method calls getUserClass, and then creates a new object using the
365     * default constructor.
366     *
367     * @return an object implementing User interface.
368     * @throws DataBackendException
369     *             if the object could not be instantiated.
370     */
371    @Override
372    public <T extends User> T getUserInstance() throws DataBackendException
373    {
374        TurbineUser u = umDelegate.getUserInstance();
375        return wrap(u);
376    }
377
378    /**
379     * Construct a blank User object.
380     *
381     * This method calls getUserClass, and then creates a new object using the
382     * default constructor.
383     *
384     * @param userName
385     *            The name of the user.
386     *
387     * @return an object implementing User interface.
388     * @throws DataBackendException
389     *             if the object could not be instantiated.
390     */
391    @Override
392    public <T extends User> T getUserInstance(String userName) throws DataBackendException
393    {
394        TurbineUser u = umDelegate.getUserInstance(userName);
395        return wrap(u);
396    }
397
398    /**
399     * Return a Class object representing the system's chosen implementation of
400     * of ACL interface.
401     *
402     * @return systems's chosen implementation of ACL interface.
403     * @throws UnknownEntityException
404     *             if the implementation of ACL interface could not be
405     *             determined, or does not exist.
406     */
407    @Override
408    public <T extends AccessControlList> T getACL(User user) throws UnknownEntityException
409    {
410        return umDelegate.getACL(user);
411    }
412}