Project

General

Profile

Download (12.5 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
	public void changePasswordForUser(String username, String newPassword) {
149
		Assert.hasText(username);
150
		Assert.hasText(newPassword);
151
		
152
		try {
153
		    User user = dao.findUserByUsername(username);
154
		    if(user == null) {
155
				throw new UsernameNotFoundException(username);
156
			}
157
		    
158
            Object salt = this.saltSource.getSalt(user);
159
			
160
			String password = passwordEncoder.encodePassword(newPassword, salt);
161
			((User)user).setPassword(password);
162
			
163
			dao.update((User)user);
164
			userCache.removeUserFromCache(user.getUsername());
165
		} catch(NonUniqueResultException nure) {
166
			throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
167
		}
168
	}
169

    
170
	@Override
171
	@Transactional(readOnly=false)
172
	public void createUser(UserDetails user) {
173
		Assert.isInstanceOf(User.class, user);
174
		
175
		String rawPassword = user.getPassword();
176
		Object salt = this.saltSource.getSalt(user);
177
		
178
		String password = passwordEncoder.encodePassword(rawPassword, salt);
179
		((User)user).setPassword(password);
180
		
181
		dao.save((User)user);
182
	}
183

    
184
	@Override
185
	@Transactional(readOnly=false)
186
	public void deleteUser(String username) {
187
		Assert.hasLength(username);
188
		
189
		User user = dao.findUserByUsername(username); 
190
        if(user != null) {		
191
		    dao.delete((User)user);
192
        }
193
        
194
        userCache.removeUserFromCache(username);
195
	}
196

    
197
	@Override
198
	@Transactional(readOnly=false)
199
	public void updateUser(UserDetails user) {
200
		Assert.isInstanceOf(User.class, user);
201
		
202
		dao.update((User)user);
203
		userCache.removeUserFromCache(user.getUsername());
204
	}
205

    
206
	@Override
207
	public boolean userExists(String username) {
208
		Assert.hasText(username);
209
		
210
		User user = dao.findUserByUsername(username);
211
		return user != null;
212
	}
213

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

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

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

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

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

    
283
	@Deprecated // use GroupService instead
284
	public List<String> findAllGroups() {
285
		return groupDao.listNames(null,null);
286
	}
287

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

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

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

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

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

    
356
	@Override
357
	public UUID update(User user) {
358
		updateUser(user);
359
		return user.getUuid(); 
360
	}
361

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

    
386
	
387

    
388
	
389
} 
(73-73/76)