remove imports
[cdmlib.git] / cdmlib-services / src / main / java / eu / etaxonomy / cdm / api / service / UserService.java
1 // $Id$
2 /**
3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
6 *
7 * The contents of this file are subject to the Mozilla Public License Version 1.1
8 * See LICENSE.TXT at the top of this package for the full license terms.
9 */
10 package eu.etaxonomy.cdm.api.service;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.UUID;
15
16 import org.hibernate.NonUniqueResultException;
17 import org.hibernate.criterion.Criterion;
18 import org.springframework.beans.factory.annotation.Autowired;
19 import org.springframework.dao.DataAccessException;
20 import org.springframework.dao.IncorrectResultSizeDataAccessException;
21
22 import org.springframework.security.access.AccessDeniedException;
23 import org.springframework.security.authentication.AuthenticationManager;
24 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
25 import org.springframework.security.authentication.dao.ReflectionSaltSource;
26 import org.springframework.security.authentication.dao.SaltSource;
27 import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
28 import org.springframework.security.authentication.encoding.PasswordEncoder;
29 import org.springframework.security.core.Authentication;
30 import org.springframework.security.core.GrantedAuthority;
31 import org.springframework.security.core.context.SecurityContextHolder;
32 import org.springframework.security.core.userdetails.UserCache;
33 import org.springframework.security.core.userdetails.UserDetails;
34 import org.springframework.security.core.userdetails.UsernameNotFoundException;
35 import org.springframework.security.core.userdetails.cache.NullUserCache;
36 import org.springframework.stereotype.Service;
37 import org.springframework.transaction.annotation.Propagation;
38 import org.springframework.transaction.annotation.Transactional;
39 import org.springframework.util.Assert;
40
41 import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
42 import eu.etaxonomy.cdm.model.common.Group;
43 import eu.etaxonomy.cdm.model.common.User;
44 import eu.etaxonomy.cdm.persistence.dao.common.IGrantedAuthorityDao;
45 import eu.etaxonomy.cdm.persistence.dao.common.IGroupDao;
46 import eu.etaxonomy.cdm.persistence.dao.common.IUserDao;
47 import eu.etaxonomy.cdm.persistence.query.MatchMode;
48 import eu.etaxonomy.cdm.persistence.query.OrderHint;
49
50 /**
51 * Note: All group related functionality has been refactored into a GroupService. The will be removed in a future version.
52 */
53 @Service
54 @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
55 public class UserService extends ServiceBase<User,IUserDao> implements IUserService {
56
57 protected IGroupDao groupDao;
58
59 protected IGrantedAuthorityDao grantedAuthorityDao;
60
61 private SaltSource saltSource = new ReflectionSaltSource();
62
63 private PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
64
65 private AuthenticationManager authenticationManager;
66
67 private UserCache userCache = new NullUserCache();
68
69 @Autowired(required = false)
70 public void setUserCache(UserCache userCache) {
71 Assert.notNull(userCache, "userCache cannot be null");
72 this.userCache = userCache;
73 }
74
75 @Autowired(required = false)
76 public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
77
78 this.passwordEncoder = passwordEncoder;
79 }
80
81 @Autowired(required = false)
82 public void setSaltSource(SaltSource saltSource) {
83 this.saltSource = saltSource;
84 }
85
86 @Autowired(required= false)
87 public void setAuthenticationManager(AuthenticationManager authenticationManager) {
88 this.authenticationManager = authenticationManager;
89 }
90
91 @Override
92 @Autowired
93 protected void setDao(IUserDao dao) {
94 this.dao = dao;
95 }
96
97 @Autowired
98 public void setGroupDao(IGroupDao groupDao) {
99 this.groupDao = groupDao;
100 }
101
102 @Autowired
103 public void setGrantedAuthorityDao(IGrantedAuthorityDao grantedAuthorityDao) {
104 this.grantedAuthorityDao = grantedAuthorityDao;
105 }
106
107 @Transactional(readOnly=false)
108 protected Authentication createNewAuthentication(Authentication currentAuth, String newPassword) {
109 UserDetails user = loadUserByUsername(currentAuth.getName());
110
111 UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
112 newAuthentication.setDetails(currentAuth.getDetails());
113
114 return newAuthentication;
115 }
116
117 @Transactional(readOnly=false)
118 public void changePassword(String oldPassword, String newPassword) {
119 Assert.hasText(oldPassword);
120 Assert.hasText(newPassword);
121 Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
122 if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
123 User user = (User)authentication.getPrincipal();
124
125 authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), oldPassword));
126
127 Object salt = this.saltSource.getSalt(user);
128
129 String password = passwordEncoder.encodePassword(newPassword, salt);
130 ((User)user).setPassword(password);
131
132 dao.update((User)user);
133 SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(authentication, newPassword));
134 userCache.removeUserFromCache(user.getUsername());
135 } else {
136 throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
137 }
138 }
139
140 @Transactional(readOnly=false)
141 public void changePasswordForUser(String username, String newPassword) {
142 Assert.hasText(username);
143 Assert.hasText(newPassword);
144
145 try {
146 User user = dao.findUserByUsername(username);
147 if(user == null) {
148 throw new UsernameNotFoundException(username);
149 }
150
151 Object salt = this.saltSource.getSalt(user);
152
153 String password = passwordEncoder.encodePassword(newPassword, salt);
154 ((User)user).setPassword(password);
155
156 dao.update((User)user);
157 userCache.removeUserFromCache(user.getUsername());
158 } catch(NonUniqueResultException nure) {
159 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
160 }
161 }
162
163 @Transactional(readOnly=false)
164 public void createUser(UserDetails user) {
165 Assert.isInstanceOf(User.class, user);
166
167 String rawPassword = user.getPassword();
168 Object salt = this.saltSource.getSalt(user);
169
170 String password = passwordEncoder.encodePassword(rawPassword, salt);
171 ((User)user).setPassword(password);
172
173 dao.save((User)user);
174 }
175
176 @Transactional(readOnly=false)
177 public void deleteUser(String username) {
178 Assert.hasLength(username);
179
180 User user = dao.findUserByUsername(username);
181 if(user != null) {
182 dao.delete((User)user);
183 }
184
185 userCache.removeUserFromCache(username);
186 }
187
188 @Transactional(readOnly=false)
189 public void updateUser(UserDetails user) {
190 Assert.isInstanceOf(User.class, user);
191
192 dao.update((User)user);
193 userCache.removeUserFromCache(user.getUsername());
194 }
195
196 public boolean userExists(String username) {
197 Assert.hasText(username);
198
199 User user = dao.findUserByUsername(username);
200 return user != null;
201 }
202
203 /**
204 * DO NOT CALL THIS METHOD IN LONG RUNNING SESSIONS OR CONVERSATIONS
205 * A THROWN UsernameNotFoundException WILL RENDER THE CONVERSATION UNUSABLE
206 */
207 public UserDetails loadUserByUsername(String username)
208 throws UsernameNotFoundException, DataAccessException {
209 Assert.hasText(username);
210 try {
211 User user = dao.findUserByUsername(username);
212 if(user == null) {
213 throw new UsernameNotFoundException(username);
214 }
215 return user;
216 } catch(NonUniqueResultException nure) {
217 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
218 }
219 }
220
221 @Deprecated // use GroupService instead
222 @Transactional(readOnly=false)
223 public void addGroupAuthority(String groupName, GrantedAuthority authority) {
224 Assert.hasText(groupName);
225 Assert.notNull(authority);
226
227 Group group = groupDao.findGroupByName(groupName);
228 if(group.getGrantedAuthorities().add(authority)) {
229 groupDao.update(group);
230 }
231 }
232
233 @Deprecated // use GroupService instead
234 @Transactional(readOnly=false)
235 public void addUserToGroup(String username, String groupName) {
236 Assert.hasText(username);
237 Assert.hasText(groupName);
238
239 Group group = groupDao.findGroupByName(groupName);
240 User user = dao.findUserByUsername(username);
241
242 if(group.addMember(user)) {
243 groupDao.update(group);
244 userCache.removeUserFromCache(user.getUsername());
245 }
246 }
247
248 @Deprecated // use GroupService instead
249 @Transactional(readOnly=false)
250 public void createGroup(String groupName, List<GrantedAuthority> authorities) {
251 Assert.hasText(groupName);
252 Assert.notNull(authorities);
253
254 Group group = Group.NewInstance(groupName);
255
256 for(GrantedAuthority authority : authorities) {
257 group.getGrantedAuthorities().add(authority);
258 }
259
260 groupDao.save(group);
261 }
262
263 @Deprecated // use GroupService instead
264 @Transactional(readOnly=false)
265 public void deleteGroup(String groupName) {
266 Assert.hasText(groupName);
267
268 Group group = groupDao.findGroupByName(groupName);
269 groupDao.delete(group);
270 }
271
272 @Deprecated // use GroupService instead
273 public List<String> findAllGroups() {
274 return groupDao.listNames(null,null);
275 }
276
277 @Deprecated // use GroupService instead
278 public List<GrantedAuthority> findGroupAuthorities(String groupName) {
279 Assert.hasText(groupName);
280 Group group = groupDao.findGroupByName(groupName);
281
282 return new ArrayList<GrantedAuthority>(group.getGrantedAuthorities());
283 }
284
285 @Deprecated // use GroupService instead
286 public List<String> findUsersInGroup(String groupName) {
287 Assert.hasText(groupName);
288 Group group = groupDao.findGroupByName(groupName);
289
290 List<String> users = groupDao.listMembers(group, null, null);
291
292 return users;
293 }
294
295 @Deprecated // use GroupService instead
296 @Transactional(readOnly=false)
297 public void removeGroupAuthority(String groupName, GrantedAuthority authority) {
298 Assert.hasText(groupName);
299 Assert.notNull(authority);
300
301 Group group = groupDao.findGroupByName(groupName);
302
303 if(group.getGrantedAuthorities().remove(authority)) {
304 groupDao.update(group);
305 }
306 }
307
308 @Deprecated // use GroupService instead
309 @Transactional(readOnly=false)
310 public void removeUserFromGroup(String username, String groupName) {
311 Assert.hasText(username);
312 Assert.hasText(groupName);
313
314 Group group = groupDao.findGroupByName(groupName);
315 User user = dao.findUserByUsername(username);
316
317 if(group.removeMember(user)) {
318 groupDao.update(group);
319 userCache.removeUserFromCache(user.getUsername());
320 }
321 }
322
323 @Transactional(readOnly=false)
324 public void renameGroup(String oldName, String newName) {
325 Assert.hasText(oldName);
326 Assert.hasText(newName);
327
328 Group group = groupDao.findGroupByName(oldName);
329
330 group.setName(newName);
331 groupDao.update(group);
332 }
333
334 @Transactional(readOnly=false)
335 public UUID save(User user) {
336 if(user.getId() == 0 || dao.load(user.getUuid()) == null){
337 createUser(user);
338 }else{
339 updateUser(user);
340 }
341 return user.getUuid();
342 }
343
344 @Override
345 public UUID update(User user) {
346 updateUser(user);
347 return user.getUuid();
348 }
349
350 @Transactional(readOnly=false)
351 public UUID saveGrantedAuthority(GrantedAuthority grantedAuthority) {
352 return grantedAuthorityDao.save((GrantedAuthorityImpl)grantedAuthority);
353 }
354
355 @Transactional(readOnly=false)
356 public UUID saveGroup(Group group) {
357 return groupDao.save(group);
358 }
359
360 @Transactional(readOnly = true)
361 public List<User> listByUsername(String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
362 Integer numberOfResults = dao.countByUsername(queryString, matchmode, criteria);
363
364 List<User> results = new ArrayList<User>();
365 if(numberOfResults > 0) {
366 results = dao.findByUsername(queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
367 }
368 return results;
369 }
370
371 }