3 * Copyright (C) 2007 EDIT
4 * European Distributed Institute of Taxonomy
5 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.api
.service
;
12 import java
.util
.List
;
13 import java
.util
.UUID
;
15 import org
.hibernate
.NonUniqueResultException
;
16 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
17 import org
.springframework
.dao
.DataAccessException
;
18 import org
.springframework
.dao
.IncorrectResultSizeDataAccessException
;
19 import org
.springframework
.security
.AccessDeniedException
;
20 import org
.springframework
.security
.Authentication
;
21 import org
.springframework
.security
.AuthenticationManager
;
22 import org
.springframework
.security
.GrantedAuthority
;
23 import org
.springframework
.security
.context
.SecurityContextHolder
;
24 import org
.springframework
.security
.providers
.UsernamePasswordAuthenticationToken
;
25 import org
.springframework
.security
.providers
.dao
.SaltSource
;
26 import org
.springframework
.security
.providers
.dao
.UserCache
;
27 import org
.springframework
.security
.providers
.dao
.cache
.NullUserCache
;
28 import org
.springframework
.security
.providers
.dao
.salt
.ReflectionSaltSource
;
29 import org
.springframework
.security
.providers
.encoding
.Md5PasswordEncoder
;
30 import org
.springframework
.security
.providers
.encoding
.PasswordEncoder
;
31 import org
.springframework
.security
.userdetails
.UserDetails
;
32 import org
.springframework
.security
.userdetails
.UsernameNotFoundException
;
33 import org
.springframework
.stereotype
.Service
;
34 import org
.springframework
.transaction
.annotation
.Transactional
;
35 import org
.springframework
.util
.Assert
;
37 import eu
.etaxonomy
.cdm
.model
.common
.GrantedAuthorityImpl
;
38 import eu
.etaxonomy
.cdm
.model
.common
.Group
;
39 import eu
.etaxonomy
.cdm
.model
.common
.User
;
40 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IGrantedAuthorityDao
;
41 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IGroupDao
;
42 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IUserDao
;
45 @Transactional(readOnly
=true)
46 public class UserService
extends ServiceBase
<User
,IUserDao
> implements IUserService
{
48 protected IGroupDao groupDao
;
50 protected IGrantedAuthorityDao grantedAuthorityDao
;
52 private SaltSource saltSource
= new ReflectionSaltSource();
54 private PasswordEncoder passwordEncoder
= new Md5PasswordEncoder();
56 private AuthenticationManager authenticationManager
;
58 private UserCache userCache
= new NullUserCache();
60 @Autowired(required
= false)
61 public void setUserCache(UserCache userCache
) {
62 Assert
.notNull(userCache
, "userCache cannot be null");
63 this.userCache
= userCache
;
66 @Autowired(required
= false)
67 public void setPasswordEncoder(PasswordEncoder passwordEncoder
) {
69 this.passwordEncoder
= passwordEncoder
;
72 @Autowired(required
= false)
73 public void setSaltSource(SaltSource saltSource
) {
74 this.saltSource
= saltSource
;
77 @Autowired(required
= false)
78 public void setAuthenticationManager(AuthenticationManager authenticationManager
) {
79 this.authenticationManager
= authenticationManager
;
84 protected void setDao(IUserDao dao
) {
89 public void setGroupDao(IGroupDao groupDao
) {
90 this.groupDao
= groupDao
;
94 public void setGrantedAuthorityDao(IGrantedAuthorityDao grantedAuthorityDao
) {
95 this.grantedAuthorityDao
= grantedAuthorityDao
;
98 @Transactional(readOnly
=false)
99 protected Authentication
createNewAuthentication(Authentication currentAuth
, String newPassword
) {
100 UserDetails user
= loadUserByUsername(currentAuth
.getName());
102 UsernamePasswordAuthenticationToken newAuthentication
= new UsernamePasswordAuthenticationToken(user
, user
.getPassword(), user
.getAuthorities());
103 newAuthentication
.setDetails(currentAuth
.getDetails());
105 return newAuthentication
;
108 @Transactional(readOnly
=false)
109 public void changePassword(String oldPassword
, String newPassword
) {
110 Assert
.hasText(oldPassword
);
111 Assert
.hasText(newPassword
);
112 Authentication authentication
= SecurityContextHolder
.getContext().getAuthentication();
113 if(authentication
!= null && authentication
.getPrincipal() != null && authentication
.getPrincipal() instanceof User
) {
114 User user
= (User
)authentication
.getPrincipal();
116 authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(user
.getUsername(), oldPassword
));
118 Object salt
= this.saltSource
.getSalt(user
);
120 String password
= passwordEncoder
.encodePassword(newPassword
, salt
);
121 ((User
)user
).setPassword(password
);
123 dao
.update((User
)user
);
124 SecurityContextHolder
.getContext().setAuthentication(createNewAuthentication(authentication
, newPassword
));
125 userCache
.removeUserFromCache(user
.getUsername());
127 throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
131 @Transactional(readOnly
=false)
132 public void changePasswordForUser(String username
, String newPassword
) {
133 Assert
.hasText(username
);
134 Assert
.hasText(newPassword
);
137 User user
= dao
.findUserByUsername(username
);
139 throw new UsernameNotFoundException(username
);
142 Object salt
= this.saltSource
.getSalt(user
);
144 String password
= passwordEncoder
.encodePassword(newPassword
, salt
);
145 ((User
)user
).setPassword(password
);
147 dao
.update((User
)user
);
148 userCache
.removeUserFromCache(user
.getUsername());
149 } catch(NonUniqueResultException nure
) {
150 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username
+ "'", 1);
154 @Transactional(readOnly
=false)
155 public void createUser(UserDetails user
) {
156 Assert
.isInstanceOf(User
.class, user
);
158 String rawPassword
= user
.getPassword();
159 Object salt
= this.saltSource
.getSalt(user
);
161 String password
= passwordEncoder
.encodePassword(rawPassword
, salt
);
162 ((User
)user
).setPassword(password
);
164 dao
.save((User
)user
);
167 @Transactional(readOnly
=false)
168 public void deleteUser(String username
) {
169 Assert
.hasLength(username
);
171 User user
= dao
.findUserByUsername(username
);
173 dao
.delete((User
)user
);
176 userCache
.removeUserFromCache(username
);
179 @Transactional(readOnly
=false)
180 public void updateUser(UserDetails user
) {
181 Assert
.isInstanceOf(User
.class, user
);
183 dao
.update((User
)user
);
184 userCache
.removeUserFromCache(user
.getUsername());
187 public boolean userExists(String username
) {
188 Assert
.hasText(username
);
190 User user
= dao
.findUserByUsername(username
);
194 public UserDetails
loadUserByUsername(String username
)
195 throws UsernameNotFoundException
, DataAccessException
{
196 Assert
.hasText(username
);
198 User user
= dao
.findUserByUsername(username
);
200 throw new UsernameNotFoundException(username
);
203 } catch(NonUniqueResultException nure
) {
204 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username
+ "'", 1);
208 @Transactional(readOnly
=false)
209 public void addGroupAuthority(String groupName
, GrantedAuthority authority
) {
210 Assert
.hasText(groupName
);
211 Assert
.notNull(authority
);
213 Group group
= groupDao
.findGroupByName(groupName
);
214 if(group
.getGrantedAuthorities().add(authority
)) {
215 groupDao
.update(group
);
219 @Transactional(readOnly
=false)
220 public void addUserToGroup(String username
, String groupName
) {
221 Assert
.hasText(username
);
222 Assert
.hasText(groupName
);
224 Group group
= groupDao
.findGroupByName(groupName
);
225 User user
= dao
.findUserByUsername(username
);
227 if(group
.addMember(user
)) {
228 groupDao
.update(group
);
229 userCache
.removeUserFromCache(user
.getUsername());
233 @Transactional(readOnly
=false)
234 public void createGroup(String groupName
, GrantedAuthority
[] authorities
) {
235 Assert
.hasText(groupName
);
236 Assert
.notNull(authorities
);
238 Group group
= new Group();
239 group
.setName(groupName
);
241 for(GrantedAuthority authority
: authorities
) {
242 group
.getGrantedAuthorities().add(authority
);
245 groupDao
.save(group
);
248 @Transactional(readOnly
=false)
249 public void deleteGroup(String groupName
) {
250 Assert
.hasText(groupName
);
252 Group group
= groupDao
.findGroupByName(groupName
);
253 groupDao
.delete(group
);
256 public String
[] findAllGroups() {
257 List
<String
> names
= groupDao
.listNames(null,null);
258 return names
.toArray(new String
[names
.size()]);
261 public GrantedAuthority
[] findGroupAuthorities(String groupName
) {
262 Assert
.hasText(groupName
);
263 Group group
= groupDao
.findGroupByName(groupName
);
265 return group
.getGrantedAuthorities().toArray(new GrantedAuthority
[group
.getGrantedAuthorities().size()]);
268 public String
[] findUsersInGroup(String groupName
) {
269 Assert
.hasText(groupName
);
270 Group group
= groupDao
.findGroupByName(groupName
);
272 List
<String
> users
= groupDao
.listMembers(group
, null, null);
274 return users
.toArray(new String
[users
.size()]);
277 @Transactional(readOnly
=false)
278 public void removeGroupAuthority(String groupName
, GrantedAuthority authority
) {
279 Assert
.hasText(groupName
);
280 Assert
.notNull(authority
);
282 Group group
= groupDao
.findGroupByName(groupName
);
284 if(group
.getGrantedAuthorities().remove(authority
)) {
285 groupDao
.update(group
);
289 @Transactional(readOnly
=false)
290 public void removeUserFromGroup(String username
, String groupName
) {
291 Assert
.hasText(username
);
292 Assert
.hasText(groupName
);
294 Group group
= groupDao
.findGroupByName(groupName
);
295 User user
= dao
.findUserByUsername(username
);
297 if(group
.removeMember(user
)) {
298 groupDao
.update(group
);
299 userCache
.removeUserFromCache(user
.getUsername());
303 @Transactional(readOnly
=false)
304 public void renameGroup(String oldName
, String newName
) {
305 Assert
.hasText(oldName
);
306 Assert
.hasText(newName
);
308 Group group
= groupDao
.findGroupByName(oldName
);
310 group
.setName(newName
);
311 groupDao
.update(group
);
314 @Transactional(readOnly
=false)
315 public UUID
save(User user
) {
316 if(user
.getId() == 0 || dao
.load(user
.getUuid()) == null){
321 return user
.getUuid();
322 // return dao.save(user);
326 public UUID
update(User user
) {
328 return user
.getUuid();
331 @Transactional(readOnly
=false)
332 public UUID
saveGrantedAuthority(GrantedAuthority grantedAuthority
) {
333 return grantedAuthorityDao
.save((GrantedAuthorityImpl
)grantedAuthority
);
336 @Transactional(readOnly
=false)
337 public UUID
saveGroup(Group group
) {
338 return groupDao
.save(group
);