Project

General

Profile

Download (10.9 KB) Statistics
| Branch: | Tag: | Revision:
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.springframework.beans.factory.annotation.Autowired;
18
import org.springframework.dao.DataAccessException;
19
import org.springframework.dao.IncorrectResultSizeDataAccessException;
20

    
21
import org.springframework.security.access.AccessDeniedException;
22
import org.springframework.security.authentication.AuthenticationManager;
23
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
24
import org.springframework.security.authentication.dao.ReflectionSaltSource;
25
import org.springframework.security.authentication.dao.SaltSource;
26
import org.springframework.security.authentication.encoding.Md5PasswordEncoder;
27
import org.springframework.security.authentication.encoding.PasswordEncoder;
28
import org.springframework.security.core.Authentication;
29
import org.springframework.security.core.GrantedAuthority;
30
import org.springframework.security.core.context.SecurityContextHolder;
31
import org.springframework.security.core.userdetails.UserCache;
32
import org.springframework.security.core.userdetails.UserDetails;
33
import org.springframework.security.core.userdetails.UsernameNotFoundException;
34
import org.springframework.security.core.userdetails.cache.NullUserCache;
35
import org.springframework.stereotype.Service;
36
import org.springframework.transaction.annotation.Propagation;
37
import org.springframework.transaction.annotation.Transactional;
38
import org.springframework.util.Assert;
39

    
40
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
41
import eu.etaxonomy.cdm.model.common.Group;
42
import eu.etaxonomy.cdm.model.common.User;
43
import eu.etaxonomy.cdm.persistence.dao.common.IGrantedAuthorityDao;
44
import eu.etaxonomy.cdm.persistence.dao.common.IGroupDao;
45
import eu.etaxonomy.cdm.persistence.dao.common.IUserDao;
46

    
47
@Service
48
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
49
public class UserService extends ServiceBase<User,IUserDao> implements IUserService {
50
	
51
	protected IGroupDao groupDao;
52
	
53
	protected IGrantedAuthorityDao grantedAuthorityDao;
54
	
55
	private SaltSource saltSource = new ReflectionSaltSource();
56
	
57
	private PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
58
	
59
	private AuthenticationManager authenticationManager;
60
	
61
	private UserCache userCache = new NullUserCache();
62
	
63
	@Autowired(required = false)
64
	public void setUserCache(UserCache userCache) {
65
		Assert.notNull(userCache, "userCache cannot be null");
66
		this.userCache = userCache;
67
	}
68
	
69
	@Autowired(required = false)
70
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
71
		
72
		this.passwordEncoder = passwordEncoder;
73
	}
74

    
75
	@Autowired(required = false)
76
	public void setSaltSource(SaltSource saltSource) {
77
		this.saltSource = saltSource;
78
	}
79
	
80
	@Autowired(required= false)
81
	public void setAuthenticationManager(AuthenticationManager authenticationManager) {
82
		this.authenticationManager = authenticationManager;
83
	}
84
	
85
	@Override
86
	@Autowired
87
	protected void setDao(IUserDao dao) {
88
		this.dao = dao;
89
	}
90
	
91
	@Autowired
92
	public void setGroupDao(IGroupDao groupDao) {
93
		this.groupDao = groupDao;
94
	}
95
	
96
	@Autowired
97
	public void setGrantedAuthorityDao(IGrantedAuthorityDao grantedAuthorityDao) {
98
		this.grantedAuthorityDao = grantedAuthorityDao;
99
	}
100
	
101
	@Transactional(readOnly=false)
102
	protected Authentication createNewAuthentication(Authentication currentAuth, String newPassword) {
103
		UserDetails user = loadUserByUsername(currentAuth.getName());
104
			
105
		UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
106
		newAuthentication.setDetails(currentAuth.getDetails());
107
			
108
		return newAuthentication;
109
	}
110
	
111
	@Transactional(readOnly=false)
112
	public void changePassword(String oldPassword, String newPassword) {
113
		Assert.hasText(oldPassword);
114
		Assert.hasText(newPassword);
115
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
116
		if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
117
			User user = (User)authentication.getPrincipal();
118
			
119
			authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), oldPassword));
120
			
121
			Object salt = this.saltSource.getSalt(user);
122
			
123
			String password = passwordEncoder.encodePassword(newPassword, salt);
124
			((User)user).setPassword(password);
125
			
126
			dao.update((User)user);
127
			SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(authentication, newPassword));
128
			userCache.removeUserFromCache(user.getUsername());
129
		} else {
130
			throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
131
		}		
132
	}
133
	
134
	@Transactional(readOnly=false)
135
	public void changePasswordForUser(String username, String newPassword) {
136
		Assert.hasText(username);
137
		Assert.hasText(newPassword);
138
		
139
		try {
140
		    User user = dao.findUserByUsername(username);
141
		    if(user == null) {
142
				throw new UsernameNotFoundException(username);
143
			}
144
		    
145
            Object salt = this.saltSource.getSalt(user);
146
			
147
			String password = passwordEncoder.encodePassword(newPassword, salt);
148
			((User)user).setPassword(password);
149
			
150
			dao.update((User)user);
151
			userCache.removeUserFromCache(user.getUsername());
152
		} catch(NonUniqueResultException nure) {
153
			throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
154
		}
155
	}
156

    
157
	@Transactional(readOnly=false)
158
	public void createUser(UserDetails user) {
159
		Assert.isInstanceOf(User.class, user);
160
		
161
		String rawPassword = user.getPassword();
162
		Object salt = this.saltSource.getSalt(user);
163
		
164
		String password = passwordEncoder.encodePassword(rawPassword, salt);
165
		((User)user).setPassword(password);
166
		
167
		dao.save((User)user);
168
	}
169

    
170
	@Transactional(readOnly=false)
171
	public void deleteUser(String username) {
172
		Assert.hasLength(username);
173
		
174
		User user = dao.findUserByUsername(username); 
175
        if(user != null) {		
176
		    dao.delete((User)user);
177
        }
178
        
179
        userCache.removeUserFromCache(username);
180
	}
181

    
182
	@Transactional(readOnly=false)
183
	public void updateUser(UserDetails user) {
184
		Assert.isInstanceOf(User.class, user);
185
		
186
		dao.update((User)user);
187
		userCache.removeUserFromCache(user.getUsername());
188
	}
189

    
190
	public boolean userExists(String username) {
191
		Assert.hasText(username);
192
		
193
		User user = dao.findUserByUsername(username);
194
		return user != null;
195
	}
196

    
197
	/**
198
	 * DO NOT CALL THIS METHOD IN LONG RUNNING SESSIONS OR CONVERSATIONS
199
	 * A THROWN UsernameNotFoundException WILL RENDER THE CONVERSATION UNUSABLE
200
	 */
201
	public UserDetails loadUserByUsername(String username)
202
			throws UsernameNotFoundException, DataAccessException {
203
		Assert.hasText(username);
204
		try {
205
		    User user = dao.findUserByUsername(username);
206
		    if(user == null) {
207
				throw new UsernameNotFoundException(username);
208
			}
209
		    return user;
210
		} catch(NonUniqueResultException nure) {
211
			throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
212
		}
213
	}
214

    
215
	@Transactional(readOnly=false)
216
	public void addGroupAuthority(String groupName, GrantedAuthority authority) {
217
		Assert.hasText(groupName);
218
		Assert.notNull(authority);
219
		
220
		Group group = groupDao.findGroupByName(groupName);
221
		if(group.getGrantedAuthorities().add(authority)) {
222
			groupDao.update(group);
223
		}
224
	}
225

    
226
	@Transactional(readOnly=false)
227
	public void addUserToGroup(String username, String groupName) {
228
		Assert.hasText(username);
229
		Assert.hasText(groupName);
230
		
231
		Group group = groupDao.findGroupByName(groupName);
232
		User user = dao.findUserByUsername(username);
233
		
234
		if(group.addMember(user)) {
235
			groupDao.update(group);
236
			userCache.removeUserFromCache(user.getUsername());
237
		}		
238
	}
239

    
240
	@Transactional(readOnly=false)
241
	public void createGroup(String groupName, List<GrantedAuthority> authorities) {
242
		Assert.hasText(groupName);
243
		Assert.notNull(authorities);
244
		
245
		Group group = new Group();
246
		group.setName(groupName);
247
		
248
		for(GrantedAuthority authority : authorities) {
249
			group.getGrantedAuthorities().add(authority);
250
		}
251
		
252
		groupDao.save(group);
253
	}
254

    
255
	@Transactional(readOnly=false)
256
	public void deleteGroup(String groupName) {
257
		Assert.hasText(groupName);
258
		
259
		Group group = groupDao.findGroupByName(groupName);
260
		groupDao.delete(group);
261
	}
262

    
263
	public List<String> findAllGroups() {
264
		return groupDao.listNames(null,null);
265
	}
266

    
267
	public List<GrantedAuthority> findGroupAuthorities(String groupName) {
268
		Assert.hasText(groupName);
269
		Group group = groupDao.findGroupByName(groupName);
270
		
271
		return new ArrayList<GrantedAuthority>(group.getGrantedAuthorities());
272
	}
273

    
274
	public List<String> findUsersInGroup(String groupName) {
275
		Assert.hasText(groupName);
276
		Group group = groupDao.findGroupByName(groupName);
277
		
278
		List<String> users = groupDao.listMembers(group, null, null);
279
		
280
		return users;
281
	}
282

    
283
	@Transactional(readOnly=false)
284
	public void removeGroupAuthority(String groupName,	GrantedAuthority authority) {
285
		Assert.hasText(groupName);
286
		Assert.notNull(authority);
287
		
288
		Group group = groupDao.findGroupByName(groupName);
289
		
290
		if(group.getGrantedAuthorities().remove(authority)) {
291
			groupDao.update(group);
292
		}
293
	}
294

    
295
	@Transactional(readOnly=false)
296
	public void removeUserFromGroup(String username, String groupName) {
297
		Assert.hasText(username);
298
		Assert.hasText(groupName);
299
		
300
		Group group = groupDao.findGroupByName(groupName);
301
		User user = dao.findUserByUsername(username);
302
		
303
		if(group.removeMember(user)) {
304
			groupDao.update(group);
305
			userCache.removeUserFromCache(user.getUsername());
306
		}
307
	}
308

    
309
	@Transactional(readOnly=false)
310
	public void renameGroup(String oldName, String newName) {
311
		Assert.hasText(oldName);
312
		Assert.hasText(newName);
313
		
314
		Group group = groupDao.findGroupByName(oldName);
315
		
316
		group.setName(newName);
317
		groupDao.update(group);
318
	}
319
	
320
	@Transactional(readOnly=false)
321
	public UUID save(User user) {
322
		if(user.getId() == 0 || dao.load(user.getUuid()) == null){
323
			createUser(user);
324
		}else{
325
			updateUser(user);
326
		}
327
		return user.getUuid(); 
328
	}
329

    
330
	@Override
331
	public UUID update(User user) {
332
		updateUser(user);
333
		return user.getUuid(); 
334
	}
335

    
336
	@Transactional(readOnly=false)
337
	public UUID saveGrantedAuthority(GrantedAuthority grantedAuthority) {
338
		return grantedAuthorityDao.save((GrantedAuthorityImpl)grantedAuthority);
339
	}
340
	
341
	@Transactional(readOnly=false)
342
	public UUID saveGroup(Group group) {
343
		return groupDao.save(group);
344
	}
345
} 
(51-51/54)