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
.Propagation
;
35 import org
.springframework
.transaction
.annotation
.Transactional
;
36 import org
.springframework
.util
.Assert
;
38 import eu
.etaxonomy
.cdm
.model
.common
.GrantedAuthorityImpl
;
39 import eu
.etaxonomy
.cdm
.model
.common
.Group
;
40 import eu
.etaxonomy
.cdm
.model
.common
.User
;
41 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IGrantedAuthorityDao
;
42 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IGroupDao
;
43 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.IUserDao
;
46 @Transactional(propagation
= Propagation
.SUPPORTS
, readOnly
= true)
47 public class UserService
extends ServiceBase
<User
,IUserDao
> implements IUserService
{
49 protected IGroupDao groupDao
;
51 protected IGrantedAuthorityDao grantedAuthorityDao
;
53 private SaltSource saltSource
= new ReflectionSaltSource();
55 private PasswordEncoder passwordEncoder
= new Md5PasswordEncoder();
57 private AuthenticationManager authenticationManager
;
59 private UserCache userCache
= new NullUserCache();
61 @Autowired(required
= false)
62 public void setUserCache(UserCache userCache
) {
63 Assert
.notNull(userCache
, "userCache cannot be null");
64 this.userCache
= userCache
;
67 @Autowired(required
= false)
68 public void setPasswordEncoder(PasswordEncoder passwordEncoder
) {
70 this.passwordEncoder
= passwordEncoder
;
73 @Autowired(required
= false)
74 public void setSaltSource(SaltSource saltSource
) {
75 this.saltSource
= saltSource
;
78 @Autowired(required
= false)
79 public void setAuthenticationManager(AuthenticationManager authenticationManager
) {
80 this.authenticationManager
= authenticationManager
;
85 protected void setDao(IUserDao dao
) {
90 public void setGroupDao(IGroupDao groupDao
) {
91 this.groupDao
= groupDao
;
95 public void setGrantedAuthorityDao(IGrantedAuthorityDao grantedAuthorityDao
) {
96 this.grantedAuthorityDao
= grantedAuthorityDao
;
99 @Transactional(readOnly
=false)
100 protected Authentication
createNewAuthentication(Authentication currentAuth
, String newPassword
) {
101 UserDetails user
= loadUserByUsername(currentAuth
.getName());
103 UsernamePasswordAuthenticationToken newAuthentication
= new UsernamePasswordAuthenticationToken(user
, user
.getPassword(), user
.getAuthorities());
104 newAuthentication
.setDetails(currentAuth
.getDetails());
106 return newAuthentication
;
109 @Transactional(readOnly
=false)
110 public void changePassword(String oldPassword
, String newPassword
) {
111 Assert
.hasText(oldPassword
);
112 Assert
.hasText(newPassword
);
113 Authentication authentication
= SecurityContextHolder
.getContext().getAuthentication();
114 if(authentication
!= null && authentication
.getPrincipal() != null && authentication
.getPrincipal() instanceof User
) {
115 User user
= (User
)authentication
.getPrincipal();
117 authenticationManager
.authenticate(new UsernamePasswordAuthenticationToken(user
.getUsername(), oldPassword
));
119 Object salt
= this.saltSource
.getSalt(user
);
121 String password
= passwordEncoder
.encodePassword(newPassword
, salt
);
122 ((User
)user
).setPassword(password
);
124 dao
.update((User
)user
);
125 SecurityContextHolder
.getContext().setAuthentication(createNewAuthentication(authentication
, newPassword
));
126 userCache
.removeUserFromCache(user
.getUsername());
128 throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
132 @Transactional(readOnly
=false)
133 public void changePasswordForUser(String username
, String newPassword
) {
134 Assert
.hasText(username
);
135 Assert
.hasText(newPassword
);
138 User user
= dao
.findUserByUsername(username
);
140 throw new UsernameNotFoundException(username
);
143 Object salt
= this.saltSource
.getSalt(user
);
145 String password
= passwordEncoder
.encodePassword(newPassword
, salt
);
146 ((User
)user
).setPassword(password
);
148 dao
.update((User
)user
);
149 userCache
.removeUserFromCache(user
.getUsername());
150 } catch(NonUniqueResultException nure
) {
151 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username
+ "'", 1);
155 @Transactional(readOnly
=false)
156 public void createUser(UserDetails user
) {
157 Assert
.isInstanceOf(User
.class, user
);
159 String rawPassword
= user
.getPassword();
160 Object salt
= this.saltSource
.getSalt(user
);
162 String password
= passwordEncoder
.encodePassword(rawPassword
, salt
);
163 ((User
)user
).setPassword(password
);
165 dao
.save((User
)user
);
168 @Transactional(readOnly
=false)
169 public void deleteUser(String username
) {
170 Assert
.hasLength(username
);
172 User user
= dao
.findUserByUsername(username
);
174 dao
.delete((User
)user
);
177 userCache
.removeUserFromCache(username
);
180 @Transactional(readOnly
=false)
181 public void updateUser(UserDetails user
) {
182 Assert
.isInstanceOf(User
.class, user
);
184 dao
.update((User
)user
);
185 userCache
.removeUserFromCache(user
.getUsername());
188 public boolean userExists(String username
) {
189 Assert
.hasText(username
);
191 User user
= dao
.findUserByUsername(username
);
195 public UserDetails
loadUserByUsername(String username
)
196 throws UsernameNotFoundException
, DataAccessException
{
197 Assert
.hasText(username
);
199 User user
= dao
.findUserByUsername(username
);
201 throw new UsernameNotFoundException(username
);
204 } catch(NonUniqueResultException nure
) {
205 throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username
+ "'", 1);
209 @Transactional(readOnly
=false)
210 public void addGroupAuthority(String groupName
, GrantedAuthority authority
) {
211 Assert
.hasText(groupName
);
212 Assert
.notNull(authority
);
214 Group group
= groupDao
.findGroupByName(groupName
);
215 if(group
.getGrantedAuthorities().add(authority
)) {
216 groupDao
.update(group
);
220 @Transactional(readOnly
=false)
221 public void addUserToGroup(String username
, String groupName
) {
222 Assert
.hasText(username
);
223 Assert
.hasText(groupName
);
225 Group group
= groupDao
.findGroupByName(groupName
);
226 User user
= dao
.findUserByUsername(username
);
228 if(group
.addMember(user
)) {
229 groupDao
.update(group
);
230 userCache
.removeUserFromCache(user
.getUsername());
234 @Transactional(readOnly
=false)
235 public void createGroup(String groupName
, GrantedAuthority
[] authorities
) {
236 Assert
.hasText(groupName
);
237 Assert
.notNull(authorities
);
239 Group group
= new Group();
240 group
.setName(groupName
);
242 for(GrantedAuthority authority
: authorities
) {
243 group
.getGrantedAuthorities().add(authority
);
246 groupDao
.save(group
);
249 @Transactional(readOnly
=false)
250 public void deleteGroup(String groupName
) {
251 Assert
.hasText(groupName
);
253 Group group
= groupDao
.findGroupByName(groupName
);
254 groupDao
.delete(group
);
257 public String
[] findAllGroups() {
258 List
<String
> names
= groupDao
.listNames(null,null);
259 return names
.toArray(new String
[names
.size()]);
262 public GrantedAuthority
[] findGroupAuthorities(String groupName
) {
263 Assert
.hasText(groupName
);
264 Group group
= groupDao
.findGroupByName(groupName
);
266 return group
.getGrantedAuthorities().toArray(new GrantedAuthority
[group
.getGrantedAuthorities().size()]);
269 public String
[] findUsersInGroup(String groupName
) {
270 Assert
.hasText(groupName
);
271 Group group
= groupDao
.findGroupByName(groupName
);
273 List
<String
> users
= groupDao
.listMembers(group
, null, null);
275 return users
.toArray(new String
[users
.size()]);
278 @Transactional(readOnly
=false)
279 public void removeGroupAuthority(String groupName
, GrantedAuthority authority
) {
280 Assert
.hasText(groupName
);
281 Assert
.notNull(authority
);
283 Group group
= groupDao
.findGroupByName(groupName
);
285 if(group
.getGrantedAuthorities().remove(authority
)) {
286 groupDao
.update(group
);
290 @Transactional(readOnly
=false)
291 public void removeUserFromGroup(String username
, String groupName
) {
292 Assert
.hasText(username
);
293 Assert
.hasText(groupName
);
295 Group group
= groupDao
.findGroupByName(groupName
);
296 User user
= dao
.findUserByUsername(username
);
298 if(group
.removeMember(user
)) {
299 groupDao
.update(group
);
300 userCache
.removeUserFromCache(user
.getUsername());
304 @Transactional(readOnly
=false)
305 public void renameGroup(String oldName
, String newName
) {
306 Assert
.hasText(oldName
);
307 Assert
.hasText(newName
);
309 Group group
= groupDao
.findGroupByName(oldName
);
311 group
.setName(newName
);
312 groupDao
.update(group
);
315 @Transactional(readOnly
=false)
316 public UUID
save(User user
) {
317 if(user
.getId() == 0 || dao
.load(user
.getUuid()) == null){
322 return user
.getUuid();
323 // return dao.save(user);
327 public UUID
update(User user
) {
329 return user
.getUuid();
332 @Transactional(readOnly
=false)
333 public UUID
saveGrantedAuthority(GrantedAuthority grantedAuthority
) {
334 return grantedAuthorityDao
.save((GrantedAuthorityImpl
)grantedAuthority
);
337 @Transactional(readOnly
=false)
338 public UUID
saveGroup(Group group
) {
339 return groupDao
.save(group
);