View Javadoc

1   /*
2    * This software was designed and created by Jason Carroll.
3    * Copyright (c) 2002, 2003, 2004 Jason Carroll.
4    * The author can be reached at jcarroll@cowsultants.com
5    * ITracker website: http://www.cowsultants.com
6    * ITracker forums: http://www.cowsultants.com/phpBB/index.php
7    *
8    * This program is free software; you can redistribute it and/or modify
9    * it only under the terms of the GNU General Public License as published by
10   * the Free Software Foundation; either version 2 of the License, or
11   * (at your option) any later version.
12   *
13   * This program is distributed in the hope that it will be useful,
14   * but WITHOUT ANY WARRANTY; without even the implied warranty of
15   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16   * GNU General Public License for more details.
17   */
18  
19  package org.itracker.services.authentication;
20  
21  import java.util.ArrayList;
22  import java.util.HashMap;
23  import java.util.List;
24  import java.util.Map;
25  
26  import org.apache.log4j.Logger;
27  import org.itracker.model.Permission;
28  import org.itracker.model.User;
29  import org.itracker.services.exceptions.AuthenticatorException;
30  import org.itracker.services.exceptions.PasswordException;
31  import org.itracker.services.exceptions.UserException;
32  import org.itracker.services.util.UserUtilities;
33  import org.jfree.util.Log;
34  import org.springframework.dao.DataAccessException;
35  
36  
37  /**
38   * This class provides a default authentication scheme for ITracker.  It uses passwords
39   * in the user table provided by ITracker to authenticate users.  This authenticator
40   * allows any user to self register if self registration is available in the system.
41   */
42  public class DefaultAuthenticator extends AbstractPluggableAuthenticator {
43  
44  	private static final Logger logger = Logger.getLogger(DefaultAuthenticator.class);
45  	
46      /**
47       * Checks the login of a user against the user profile provided in ITracker.  This is
48       * the default authentication scheme provided by ITracker.
49       *
50       * @param login          the login the user/client provided
51       * @param authentication the user's authentication information, if known
52       * @param authType       the type of authentication information being provided
53       * @param reqSource      the source of the request (eg web, api)
54       * @return a User if the login is successful
55       * @throws AuthenticatorException an exception if the login is unsuccessful, or an error occurs
56       */
57      public User checkLogin(final String login, final Object authentication, final int authType, final int reqSource) throws AuthenticatorException {
58          if (logger.isDebugEnabled()) {
59              logger.debug("Checking login for " + login + " using DefaultAuthenticator");
60          }
61  
62          if (login != null && authentication != null && !login.equals("")) {
63              User user;
64              try {
65                  user = getUserService().getUserByLogin(login);
66              } catch (DataAccessException e) {
67              	logger.error("checkLogin: failed to get user by login: " + login, e);
68                  throw new AuthenticatorException(AuthenticatorException.UNKNOWN_USER, e.getMessage());
69              }
70  
71  //            if (user == null) {
72  //                AuthenticatorException e =  new AuthenticatorException(AuthenticatorException.UNKNOWN_USER);
73  //                logger.error("checkLogin: failed to get user by login: " + login, e);
74  //                throw e;
75  //            }
76              if (user.getStatus() != UserUtilities.STATUS_ACTIVE) {
77              	AuthenticatorException e =  new AuthenticatorException(AuthenticatorException.INACTIVE_ACCOUNT);
78              	logger.info("checkLogin: user is inactive, user: " + user, e);
79                  throw e; 
80              }
81  
82              String userPassword;
83              try {
84                  userPassword = getUserService().getUserPasswordByLogin(login);
85              } catch (DataAccessException e) {
86                  AuthenticatorException ex = new AuthenticatorException(e.getMessage(), authType);
87                  logger.info("checkLogin: user is inactive, user: " + user, ex);
88                  throw e;
89              }
90              if (userPassword == null || userPassword.equals("")) {
91                  AuthenticatorException e = new AuthenticatorException(AuthenticatorException.INVALID_PASSWORD);
92                  logger.info("checkLogin: user has no password, user: " + user, e);
93                  throw e;
94              }
95  
96              try {
97                  if (!userPassword.endsWith("=")) {
98                      logger.info("checkLogin: User " + login + " has old style password.  Converting to SHA1 hash.");
99                      try {
100                         user.setPassword(UserUtilities.encryptPassword(userPassword));
101                         getUserService().updateUser(user);
102                     } catch (UserException ue) {
103                         logger.error("checkLogin: User password conversion failed for user " + user, ue);
104                         throw new AuthenticatorException(AuthenticatorException.SYSTEM_ERROR);
105                     }
106                 }
107 
108                 if (authType == AUTH_TYPE_PASSWORD_PLAIN) {
109                     if (!userPassword.equals(UserUtilities.encryptPassword((String) authentication))) {
110                         throw new AuthenticatorException(AuthenticatorException.INVALID_PASSWORD);                        
111                     }
112                 } else if (authType == AUTH_TYPE_PASSWORD_ENC) {
113                     if (!userPassword.equals(authentication)) {
114                         throw new AuthenticatorException(AuthenticatorException.INVALID_PASSWORD);
115                     }
116                 } else {
117                 	logger.info("checkLogin: invalid authenticator type: " + authType);
118                     throw new AuthenticatorException(AuthenticatorException.INVALID_AUTHENTICATION_TYPE);
119                 }
120             } catch (ClassCastException cce) {
121                 logger.error("checkLogin: Authenticator was of wrong type.", cce);
122                 throw new AuthenticatorException(AuthenticatorException.SYSTEM_ERROR);
123             } catch (PasswordException pe) {
124                 throw new AuthenticatorException(AuthenticatorException.SYSTEM_ERROR);
125             } catch (AuthenticatorException ae) {
126             	if (logger.isDebugEnabled()) {
127             		logger.debug("checkLogin: failed to authenticate " + login, ae);
128             	}
129             	throw ae;
130             }
131 
132             return user;
133         }
134 
135     	Log.info("checkLogin: no login was supplied: " + login + ", type: " + authType + ", source: " + reqSource);
136         throw new AuthenticatorException(AuthenticatorException.INVALID_DATA);
137     }
138 
139     /**
140      * The DefaultAuthenticator returns a list of user permissions from the database.
141      *
142      * @param user      a User object that contains the user to retrieve permissions for
143      * @param reqSource the source of the request (eg web, api)
144      * @return an array of PermissionModels
145      * @throws AuthenticatorException an error occurs
146      */
147     public List<Permission> getUserPermissions(User user, int reqSource) throws AuthenticatorException {
148         if (user == null || user.getId() == null) {
149             throw new AuthenticatorException(AuthenticatorException.INVALID_DATA);
150         }
151 
152         List<Permission> permissionList;
153         try {
154             permissionList = getUserService().getUserPermissionsLocal(user);
155         } catch (DataAccessException e) {
156             throw new AuthenticatorException(e.getMessage(), reqSource);
157         }
158 
159         if (user.isSuperUser()) {
160             List<Permission> augmentedPermissions = new ArrayList<Permission>();
161 
162             // Super user has access to all projects (represented by the "null" project). 
163             Permission permission = new Permission(-1, user, null);
164             augmentedPermissions.add(permission);
165             augmentedPermissions.addAll(permissionList);
166             return augmentedPermissions;
167 
168         } else {
169             return permissionList;
170         }
171 
172     }
173 
174     /**
175      * Returns the list of users for a given project. User permissions can be specified.
176      *
177      * @param projectId       - The Project to search for users
178      * @param permissionTypes - User rights to filter
179      * @param requireAll      - Require all permissions
180      * @param activeOnly      - Filter users who are active (Possible user status: DELETED, ACTIVE, LOCKED)
181      * @param reqSource       - not used. TODO: Tagged for removal
182      * @return List of users for the project with filters applied.
183      * @throws AuthenticatorException
184      */
185     public List<User> getUsersWithProjectPermission(Integer projectId,
186                                                     int[] permissionTypes,
187                                                     boolean requireAll,
188                                                     boolean activeOnly,
189                                                     int reqSource)
190             throws AuthenticatorException {
191 
192         List<User> users;
193 
194         try {
195             Map<Integer, User> userMap = new HashMap<Integer, User>();
196 
197             if (requireAll) {
198 
199                 Integer[] types = new Integer[permissionTypes.length];
200                 for (int i = 0; i < types.length; i++) {
201                     types[i] = permissionTypes[i];
202                 }
203 
204                 List<User> explicitUsers = getUserService().findUsersForProjectByPermissionTypeList(projectId, types);
205 
206                 for (User user : explicitUsers) {
207                     userMap.put(user.getId(), user);
208                 }
209             } else {
210 
211                 for (int i = 0; i < permissionTypes.length; i++) {
212                     List<User> explicitUsers = getUserService().getUsersWithPermissionLocal(projectId, permissionTypes[i]);
213 
214                     for (User user : explicitUsers) {
215                         userMap.put(user.getId(), user);
216                     }
217 
218                 }
219 
220             }
221 
222             List<User> superUsers = getUserService().getSuperUsers();
223             for (User superUser : superUsers) {
224                 userMap.put(superUser.getId(), superUser);
225             }
226 
227             users = new ArrayList<User>();
228             for (User user : userMap.values()) {
229                 if (activeOnly) {
230                     if (user.getStatus() == UserUtilities.STATUS_ACTIVE) {
231                         users.add(user);
232                     }
233                 } else {
234                     users.add(user);
235                 }
236             }
237 
238         } catch (Exception e) {
239             logger.error("Error retreiving users with permissions.", e);
240             throw new AuthenticatorException();
241         }
242 
243         return users;
244 
245     }
246 
247     /**
248      * The DefaultAuthenticator always allows self registered users.
249      *
250      * @param user           a User object that contains the data the user submitted
251      * @param authentication the user's authentication information, if known
252      * @param authType       the type of authentication information being provided
253      * @param reqSource      the source of the request (eg web, api)
254      * @return true
255      */
256     public boolean allowRegistration(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
257         return true;
258     }
259 
260 
261     /**
262      * The DefaultAuthenticator always allows new user profiles.
263      *
264      * @param user           a User object that contains the data the user submitted
265      * @param authentication the user's authentication information, if known
266      * @param authType       the type of authentication information being provided
267      * @return true
268      * @throws AuthenticatorException an exception if an error occurs
269      */
270     public boolean allowProfileCreation(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
271         return true;
272     }
273 
274     /**
275      * The DefaultAuthenticator always allows profile updates.
276      *
277      * @param user           a User object that contains the data the user submitted
278      * @param authentication the user's authentication information, if known
279      * @param authType       the type of authentication information being provided
280      * @param reqSource      the source of the request (eg web, api)
281      * @return true
282      * @throws AuthenticatorException an exception if an error occurs
283      */
284     public boolean allowProfileUpdates(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
285         return true;
286     }
287 
288     /**
289      * The DefaultAuthenticator always allows password updates.
290      *
291      * @param user           a User object that contains the data the user submitted
292      * @param authentication the user's authentication information, if known
293      * @param authType       the type of authentication information being provided
294      * @param reqSource      the source of the request (eg web, api)
295      * @return true
296      * @throws AuthenticatorException an exception if an error occurs
297      */
298     public boolean allowPasswordUpdates(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
299         return true;
300     }
301 
302     /**
303      * The DefaultAuthenticator always allows permission updates.
304      *
305      * @param user           a User object that contains the data the user submitted
306      * @param authentication the user's authentication information, if known
307      * @param authType       the type of authentication information being provided
308      * @param reqSource      the source of the request (eg web, api)
309      * @return true
310      * @throws AuthenticatorException an exception if an error occurs
311      */
312     public boolean allowPermissionUpdates(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
313         return true;
314     }
315 
316     /**
317      * The DefaultAuthenticator always allows preferences updates.
318      *
319      * @param user           a User object that contains the data the user submitted
320      * @param authentication the user's authentication information, if known
321      * @param authType       the type of authentication information being provided
322      * @param reqSource      the source of the request (eg web, api)
323      * @return true
324      * @throws AuthenticatorException an exception if an error occurs
325      */
326     public boolean allowPreferenceUpdates(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
327         return true;
328     }
329 
330     /**
331      * The DefaultAuthenticator does not make any changes to a newly created profile.
332      *
333      * @param user           a User object that contains the newly created profile
334      * @param authentication the user's authentication information, if known
335      * @param authType       the type of authentication information being provided
336      * @param reqSource      the source of the request (eg web, api)
337      * @return boolean indicating whther changes to the user were made
338      * @throws AuthenticatorException an error occurs
339      */
340     public boolean createProfile(User user, Object authentication, int authType, int reqSource) throws AuthenticatorException {
341         return false;
342     }
343 
344     /**
345      * The DefaultAuthenticator does not make any changes to an updated profile.
346      *
347      * @param user           a User object that contains the updated profile
348      * @param updateType     the type of information that is being updated
349      * @param authentication the user's authentication information, if known
350      * @param authType       the type of authentication information being provided
351      * @param reqSource      the source of the request (eg web, api)
352      * @return boolean indicating whther changes to the user were made
353      * @throws AuthenticatorException an exception if the login is unsuccessful, or an error occurs
354      */
355     public boolean updateProfile(User user, int updateType, Object authentication, int authType, int reqSource) throws AuthenticatorException {
356         return false;
357     }
358 
359 }