Project

General

Profile

Download (12.8 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.security.Permission;
13
import java.util.ArrayList;
14
import java.util.List;
15
import java.util.UUID;
16

    
17
import org.hibernate.NonUniqueResultException;
18
import org.hibernate.criterion.Criterion;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.dao.DataAccessException;
21
import org.springframework.dao.IncorrectResultSizeDataAccessException;
22

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

    
43
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
44
import eu.etaxonomy.cdm.model.common.Group;
45
import eu.etaxonomy.cdm.model.common.User;
46
import eu.etaxonomy.cdm.permission.CdmPermission;
47
import eu.etaxonomy.cdm.permission.CdmPermissionEvaluator;
48
import eu.etaxonomy.cdm.persistence.dao.common.IGrantedAuthorityDao;
49
import eu.etaxonomy.cdm.persistence.dao.common.IGroupDao;
50
import eu.etaxonomy.cdm.persistence.dao.common.IUserDao;
51
import eu.etaxonomy.cdm.persistence.query.MatchMode;
52
import eu.etaxonomy.cdm.persistence.query.OrderHint;
53

    
54
/**
55
 * Note: All group related functionality has been refactored into a GroupService. The will be removed in a future version.
56
 */
57
@Service
58
@Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
59
public class UserService extends ServiceBase<User,IUserDao> implements IUserService {
60
	
61
	protected IGroupDao groupDao;
62
	
63
	protected IGrantedAuthorityDao grantedAuthorityDao;
64
	
65
	private SaltSource saltSource = new ReflectionSaltSource();
66
	
67
	private PasswordEncoder passwordEncoder = new Md5PasswordEncoder();
68
	
69
	private AuthenticationManager authenticationManager;
70
	
71
	private UserCache userCache = new NullUserCache();
72
	
73
	@Autowired(required = false)
74
	public void setUserCache(UserCache userCache) {
75
		Assert.notNull(userCache, "userCache cannot be null");
76
		this.userCache = userCache;
77
	}
78
	
79
	@Autowired(required = false)
80
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
81
		
82
		this.passwordEncoder = passwordEncoder;
83
	}
84

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

    
171
	@Override
172
	@Transactional(readOnly=false)
173
	@PreAuthorize("hasRole('ALL.ADMIN') or hasPermission(#user, 'CREATE')")
174
	public void createUser(UserDetails user) {
175
		Assert.isInstanceOf(User.class, user);
176
		
177
		String rawPassword = user.getPassword();
178
		Object salt = this.saltSource.getSalt(user);
179
		
180
		String password = passwordEncoder.encodePassword(rawPassword, salt);
181
		((User)user).setPassword(password);
182
		
183
		dao.save((User)user);
184
	}
185

    
186
	@Override
187
	@Transactional(readOnly=false)
188
	@PreAuthorize("hasRole('ALL.ADMIN') or hasPermission(#username, 'DELETE')")
189
	public void deleteUser(String username) {
190
		Assert.hasLength(username);
191
		
192
		User user = dao.findUserByUsername(username); 
193
        if(user != null) {		
194
		    dao.delete((User)user);
195
        }
196
        
197
        userCache.removeUserFromCache(username);
198
	}
199

    
200
	@Override
201
	@Transactional(readOnly=false)
202
	@PreAuthorize("hasRole('ALL.ADMIN') or hasPermission(#user, 'UPDATE')")
203
	public void updateUser(UserDetails user) {
204
		Assert.isInstanceOf(User.class, user);
205
		
206
		dao.update((User)user);
207
		userCache.removeUserFromCache(user.getUsername());
208
	}
209

    
210
	@Override
211
	public boolean userExists(String username) {
212
		Assert.hasText(username);
213
		
214
		User user = dao.findUserByUsername(username);
215
		return user != null;
216
	}
217

    
218
	/**
219
	 * DO NOT CALL THIS METHOD IN LONG RUNNING SESSIONS OR CONVERSATIONS
220
	 * A THROWN UsernameNotFoundException WILL RENDER THE CONVERSATION UNUSABLE
221
	 */
222
	public UserDetails loadUserByUsername(String username)
223
			throws UsernameNotFoundException, DataAccessException {
224
		Assert.hasText(username);
225
		try {
226
		    User user = dao.findUserByUsername(username);
227
		    if(user == null) {
228
				throw new UsernameNotFoundException(username);
229
			}
230
		    return user;
231
		} catch(NonUniqueResultException nure) {
232
			throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
233
		}
234
	}
235

    
236
	@Deprecated // use GroupService instead
237
	@Transactional(readOnly=false)
238
	public void addGroupAuthority(String groupName, GrantedAuthority authority) {
239
		Assert.hasText(groupName);
240
		Assert.notNull(authority);
241
		
242
		Group group = groupDao.findGroupByName(groupName);
243
		if(group.getGrantedAuthorities().add(authority)) {
244
			groupDao.update(group);
245
		}
246
	}
247

    
248
	@Deprecated // use GroupService instead
249
	@Transactional(readOnly=false)
250
	public void addUserToGroup(String username, String groupName) {
251
		Assert.hasText(username);
252
		Assert.hasText(groupName);
253
		
254
		Group group = groupDao.findGroupByName(groupName);
255
		User user = dao.findUserByUsername(username);
256
		
257
		if(group.addMember(user)) {
258
			groupDao.update(group);
259
			userCache.removeUserFromCache(user.getUsername());
260
		}		
261
	}
262

    
263
	@Deprecated // use GroupService instead
264
	@Transactional(readOnly=false)
265
	public void createGroup(String groupName, List<GrantedAuthority> authorities) {
266
		Assert.hasText(groupName);
267
		Assert.notNull(authorities);
268
		
269
		Group group = Group.NewInstance(groupName);
270
		
271
		for(GrantedAuthority authority : authorities) {
272
			group.getGrantedAuthorities().add(authority);
273
		}
274
		
275
		groupDao.save(group);
276
	}
277

    
278
	@Deprecated // use GroupService instead
279
	@Transactional(readOnly=false)
280
	public void deleteGroup(String groupName) {
281
		Assert.hasText(groupName);
282
		
283
		Group group = groupDao.findGroupByName(groupName);
284
		groupDao.delete(group);
285
	}
286

    
287
	@Deprecated // use GroupService instead
288
	public List<String> findAllGroups() {
289
		return groupDao.listNames(null,null);
290
	}
291

    
292
	@Deprecated // use GroupService instead
293
	public List<GrantedAuthority> findGroupAuthorities(String groupName) {
294
		Assert.hasText(groupName);
295
		Group group = groupDao.findGroupByName(groupName);
296
		
297
		return new ArrayList<GrantedAuthority>(group.getGrantedAuthorities());
298
	}
299

    
300
	@Deprecated // use GroupService instead
301
	public List<String> findUsersInGroup(String groupName) {
302
		Assert.hasText(groupName);
303
		Group group = groupDao.findGroupByName(groupName);
304
		
305
		List<String> users = groupDao.listMembers(group, null, null);
306
		
307
		return users;
308
	}
309

    
310
	@Deprecated // use GroupService instead
311
	@Transactional(readOnly=false)
312
	public void removeGroupAuthority(String groupName,	GrantedAuthority authority) {
313
		Assert.hasText(groupName);
314
		Assert.notNull(authority);
315
		
316
		Group group = groupDao.findGroupByName(groupName);
317
		
318
		if(group.getGrantedAuthorities().remove(authority)) {
319
			groupDao.update(group);
320
		}
321
	}
322

    
323
	@Deprecated // use GroupService instead
324
	@Transactional(readOnly=false)
325
	public void removeUserFromGroup(String username, String groupName) {
326
		Assert.hasText(username);
327
		Assert.hasText(groupName);
328
		
329
		Group group = groupDao.findGroupByName(groupName);
330
		User user = dao.findUserByUsername(username);
331
		
332
		if(group.removeMember(user)) {
333
			groupDao.update(group);
334
			userCache.removeUserFromCache(user.getUsername());
335
		}
336
	}
337

    
338
	@Deprecated // use GroupService instead
339
	@Transactional(readOnly=false)
340
	public void renameGroup(String oldName, String newName) {
341
		Assert.hasText(oldName);
342
		Assert.hasText(newName);
343
		
344
		Group group = groupDao.findGroupByName(oldName);
345
		
346
		group.setName(newName);
347
		groupDao.update(group);
348
	}
349
	
350
	@Transactional(readOnly=false)
351
	public UUID save(User user) {
352
		if(user.getId() == 0 || dao.load(user.getUuid()) == null){
353
			createUser(user);
354
		}else{
355
			updateUser(user);
356
		}
357
		return user.getUuid(); 
358
	}
359

    
360
	@Override
361
	public UUID update(User user) {
362
		updateUser(user);
363
		return user.getUuid(); 
364
	}
365

    
366
	@Override
367
	@Transactional(readOnly=false)
368
	public UUID saveGrantedAuthority(GrantedAuthority grantedAuthority) {
369
		return grantedAuthorityDao.save((GrantedAuthorityImpl)grantedAuthority);
370
	}
371
	
372
	@Deprecated // use GroupService instead
373
	@Transactional(readOnly=false)
374
	public UUID saveGroup(Group group) {
375
		return groupDao.save(group);
376
	}
377
	
378
	@Override
379
	@Transactional(readOnly = true)
380
	public List<User> listByUsername(String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
381
		 Integer numberOfResults = dao.countByUsername(queryString, matchmode, criteria);
382
			
383
		 List<User> results = new ArrayList<User>();
384
		 if(numberOfResults > 0) { 
385
				results = dao.findByUsername(queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths); 
386
		 }
387
		 return results;
388
	}
389

    
390
	
391

    
392
	
393
} 
(76-76/79)