Project

General

Profile

Download (17.1 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.Collection;
14
import java.util.List;
15
import java.util.Map;
16
import java.util.UUID;
17

    
18
import org.hibernate.NonUniqueResultException;
19
import org.hibernate.criterion.Criterion;
20
import org.springframework.beans.factory.annotation.Autowired;
21
import org.springframework.dao.DataAccessException;
22
import org.springframework.dao.IncorrectResultSizeDataAccessException;
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.SaltSource;
28
import org.springframework.security.authentication.encoding.PasswordEncoder;
29
import org.springframework.security.core.Authentication;
30
import org.springframework.security.core.GrantedAuthority;
31
import org.springframework.security.core.context.SecurityContextHolder;
32
import org.springframework.security.core.userdetails.UserCache;
33
import org.springframework.security.core.userdetails.UserDetails;
34
import org.springframework.security.core.userdetails.UsernameNotFoundException;
35
import org.springframework.security.core.userdetails.cache.NullUserCache;
36
import org.springframework.stereotype.Service;
37
import org.springframework.transaction.annotation.Propagation;
38
import org.springframework.transaction.annotation.Transactional;
39
import org.springframework.util.Assert;
40

    
41
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
42
import eu.etaxonomy.cdm.model.common.Group;
43
import eu.etaxonomy.cdm.model.common.User;
44
import eu.etaxonomy.cdm.persistence.dao.common.IGrantedAuthorityDao;
45
import eu.etaxonomy.cdm.persistence.dao.common.IGroupDao;
46
import eu.etaxonomy.cdm.persistence.dao.common.IUserDao;
47
import eu.etaxonomy.cdm.persistence.query.MatchMode;
48
import eu.etaxonomy.cdm.persistence.query.OrderHint;
49

    
50
/**
51
 * Note: All group related functionality has been refactored into a GroupService. The will be removed in a future version.
52
 */
53
@Service
54
@Transactional(readOnly = true)
55
// NOTE: no type level @PreAuthorize annotation for this class!
56
public class UserService extends ServiceBase<User,IUserDao> implements IUserService {
57

    
58
    protected IGroupDao groupDao;
59

    
60
    protected IGrantedAuthorityDao grantedAuthorityDao;
61

    
62
    private SaltSource saltSource; // = new ReflectionSaltSource();
63

    
64
    private PasswordEncoder passwordEncoder; // = new Md5PasswordEncoder();
65

    
66
    private AuthenticationManager authenticationManager;
67

    
68
    private UserCache userCache = new NullUserCache();
69

    
70
    @Autowired(required = false)
71
    public void setUserCache(UserCache userCache) {
72
        Assert.notNull(userCache, "userCache cannot be null");
73
        this.userCache = userCache;
74
    }
75

    
76
    @Autowired(required = false)
77
    public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
78

    
79
        this.passwordEncoder = passwordEncoder;
80
    }
81

    
82
    @Autowired(required = false)
83
    public void setSaltSource(SaltSource saltSource) {
84
        this.saltSource = saltSource;
85
    }
86

    
87
    @Autowired(required= false)
88
    public void setAuthenticationManager(AuthenticationManager authenticationManager) {
89
        this.authenticationManager = authenticationManager;
90
    }
91

    
92
    @Override
93
    @Autowired
94
    protected void setDao(IUserDao dao) {
95
        this.dao = dao;
96
    }
97

    
98
    @Autowired
99
    public void setGroupDao(IGroupDao groupDao) {
100
        this.groupDao = groupDao;
101
    }
102

    
103
    @Autowired
104
    public void setGrantedAuthorityDao(IGrantedAuthorityDao grantedAuthorityDao) {
105
        this.grantedAuthorityDao = grantedAuthorityDao;
106
    }
107

    
108
    @Transactional(readOnly=false)
109
    protected Authentication createNewAuthentication(Authentication currentAuth, String newPassword) {
110
        UserDetails user = loadUserByUsername(currentAuth.getName());
111

    
112
        UsernamePasswordAuthenticationToken newAuthentication = new UsernamePasswordAuthenticationToken(user, user.getPassword(), user.getAuthorities());
113
        newAuthentication.setDetails(currentAuth.getDetails());
114

    
115
        return newAuthentication;
116
    }
117

    
118
    @Override
119
    @Transactional(readOnly=false)
120
    @PreAuthorize("isAuthenticated()")
121
    public void changePassword(String oldPassword, String newPassword) {
122
        Assert.hasText(oldPassword);
123
        Assert.hasText(newPassword);
124
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
125
        if(authentication != null && authentication.getPrincipal() != null && authentication.getPrincipal() instanceof User) {
126
            User user = (User)authentication.getPrincipal();
127

    
128
            authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), oldPassword));
129

    
130
            Object salt = this.saltSource.getSalt(user);
131

    
132
            String password = passwordEncoder.encodePassword(newPassword, salt);
133
            ((User)user).setPassword(password);
134

    
135
            dao.update((User)user);
136
            SecurityContextHolder.getContext().setAuthentication(createNewAuthentication(authentication, newPassword));
137
            userCache.removeUserFromCache(user.getUsername());
138
        } else {
139
            throw new AccessDeniedException("Can't change password as no Authentication object found in context for current user.");
140
        }
141
    }
142

    
143
    /* (non-Javadoc)
144
     * @see eu.etaxonomy.cdm.api.service.IUserService#changePasswordForUser(java.lang.String, java.lang.String)
145
     */
146
    @Override
147
    @Transactional(readOnly=false)
148
    @PreAuthorize("#username == authentication.name or hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
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
    /* (non-Javadoc)
172
     * @see org.springframework.security.provisioning.UserDetailsManager#createUser(org.springframework.security.core.userdetails.UserDetails)
173
     */
174
    @Override
175
    @Transactional(readOnly=false)
176
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
177
    public void createUser(UserDetails user) {
178
        Assert.isInstanceOf(User.class, user);
179

    
180
        String rawPassword = user.getPassword();
181
        Object salt = this.saltSource.getSalt(user);
182

    
183
        String password = passwordEncoder.encodePassword(rawPassword, salt);
184
        ((User)user).setPassword(password);
185

    
186
        dao.save((User)user);
187
    }
188

    
189
    /* (non-Javadoc)
190
     * @see org.springframework.security.provisioning.UserDetailsManager#deleteUser(java.lang.String)
191
     */
192
    @Override
193
    @Transactional(readOnly=false)
194
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
195
    public void deleteUser(String username) {
196
        Assert.hasLength(username);
197

    
198
        User user = dao.findUserByUsername(username);
199
        if(user != null) {
200
            dao.delete((User)user);
201
        }
202

    
203
        userCache.removeUserFromCache(username);
204
    }
205

    
206
    /* (non-Javadoc)
207
     * @see org.springframework.security.provisioning.UserDetailsManager#updateUser(org.springframework.security.core.userdetails.UserDetails)
208
     */
209
    @Override
210
    @Transactional(readOnly=false)
211
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
212
    public void updateUser(UserDetails user) {
213
        Assert.isInstanceOf(User.class, user);
214

    
215
        dao.update((User)user);
216
        userCache.removeUserFromCache(user.getUsername());
217
    }
218

    
219
    /* (non-Javadoc)
220
     * @see org.springframework.security.provisioning.UserDetailsManager#userExists(java.lang.String)
221
     */
222
    @Override
223
    public boolean userExists(String username) {
224
        Assert.hasText(username);
225

    
226
        User user = dao.findUserByUsername(username);
227
        return user != null;
228
    }
229

    
230
    /**
231
     * <b>DO NOT CALL THIS METHOD IN LONG RUNNING SESSIONS OR CONVERSATIONS
232
     * A THROWN UsernameNotFoundException WILL RENDER THE CONVERSATION UNUSABLE</b>
233
     *
234
     * @see org.springframework.security.core.userdetails.UserDetailsService#loadUserByUsername(java.lang.String)
235
     */
236
    // NOTE: this method must not be secured since it is being used during the
237
    //       authentication process
238
    public UserDetails loadUserByUsername(String username)
239
            throws UsernameNotFoundException, DataAccessException {
240
        Assert.hasText(username);
241
        try {
242
            User user = dao.findUserByUsername(username);
243
            if(user == null) {
244
                throw new UsernameNotFoundException(username);
245
            }
246
            return user;
247
        } catch(NonUniqueResultException nure) {
248
            throw new IncorrectResultSizeDataAccessException("More than one user found with name '" + username + "'", 1);
249
        }
250
    }
251

    
252
    @Deprecated // use GroupService instead
253
    @Transactional(readOnly=false)
254
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
255
    public void addGroupAuthority(String groupName, GrantedAuthority authority) {
256
        Assert.hasText(groupName);
257
        Assert.notNull(authority);
258

    
259
        Group group = groupDao.findGroupByName(groupName);
260
        if(group.getGrantedAuthorities().add(authority)) {
261
            groupDao.update(group);
262
        }
263
    }
264

    
265
    @Deprecated // use GroupService instead
266
    @Transactional(readOnly=false)
267
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
268
    public void addUserToGroup(String username, String groupName) {
269
        Assert.hasText(username);
270
        Assert.hasText(groupName);
271

    
272
        Group group = groupDao.findGroupByName(groupName);
273
        User user = dao.findUserByUsername(username);
274

    
275
        if(group.addMember(user)) {
276
            groupDao.update(group);
277
            userCache.removeUserFromCache(user.getUsername());
278
        }
279
    }
280

    
281
    @Deprecated // use GroupService instead
282
    @Transactional(readOnly=false)
283
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
284
    public void createGroup(String groupName, List<GrantedAuthority> authorities) {
285
        Assert.hasText(groupName);
286
        Assert.notNull(authorities);
287

    
288
        Group group = Group.NewInstance(groupName);
289

    
290
        for(GrantedAuthority authority : authorities) {
291
            group.getGrantedAuthorities().add(authority);
292
        }
293

    
294
        groupDao.save(group);
295
    }
296

    
297
    @Deprecated // use GroupService instead
298
    @Transactional(readOnly=false)
299
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
300
    public void deleteGroup(String groupName) {
301
        Assert.hasText(groupName);
302

    
303
        Group group = groupDao.findGroupByName(groupName);
304
        groupDao.delete(group);
305
    }
306

    
307
    @Deprecated // use GroupService instead
308
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
309
    public List<String> findAllGroups() {
310
        return groupDao.listNames(null,null);
311
    }
312

    
313
    @Deprecated // use GroupService instead
314
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
315
    public List<GrantedAuthority> findGroupAuthorities(String groupName) {
316
        Assert.hasText(groupName);
317
        Group group = groupDao.findGroupByName(groupName);
318

    
319
        return new ArrayList<GrantedAuthority>(group.getGrantedAuthorities());
320
    }
321

    
322
    @Deprecated // use GroupService instead
323
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
324
    public List<String> findUsersInGroup(String groupName) {
325
        Assert.hasText(groupName);
326
        Group group = groupDao.findGroupByName(groupName);
327

    
328
        List<String> users = groupDao.listMembers(group, null, null);
329

    
330
        return users;
331
    }
332

    
333
    @Deprecated // use GroupService instead
334
    @Transactional(readOnly=false)
335
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
336
    public void removeGroupAuthority(String groupName,	GrantedAuthority authority) {
337
        Assert.hasText(groupName);
338
        Assert.notNull(authority);
339

    
340
        Group group = groupDao.findGroupByName(groupName);
341

    
342
        if(group.getGrantedAuthorities().remove(authority)) {
343
            groupDao.update(group);
344
        }
345
    }
346

    
347
    @Deprecated // use GroupService instead
348
    @Transactional(readOnly=false)
349
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
350
    public void removeUserFromGroup(String username, String groupName) {
351
        Assert.hasText(username);
352
        Assert.hasText(groupName);
353

    
354
        Group group = groupDao.findGroupByName(groupName);
355
        User user = dao.findUserByUsername(username);
356

    
357
        if(group.removeMember(user)) {
358
            groupDao.update(group);
359
            userCache.removeUserFromCache(user.getUsername());
360
        }
361
    }
362

    
363
    @Deprecated // use GroupService instead
364
    @Transactional(readOnly=false)
365
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
366
    public void renameGroup(String oldName, String newName) {
367
        Assert.hasText(oldName);
368
        Assert.hasText(newName);
369

    
370
        Group group = groupDao.findGroupByName(oldName);
371

    
372
        group.setName(newName);
373
        groupDao.update(group);
374
    }
375

    
376
    @Transactional(readOnly=false)
377
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_RUN_AS_ADMIN') or hasRole('ROLE_USER_MANAGER')")
378
    public UUID save(User user) {
379
        if(user.getId() == 0 || dao.load(user.getUuid()) == null){
380
            createUser(user);
381
        }else{
382
            updateUser(user);
383
        }
384
        return user.getUuid();
385
    }
386

    
387
    @Override
388
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
389
    public UUID update(User user) {
390
        updateUser(user);
391
        return user.getUuid();
392
    }
393

    
394
    @Override
395
    @Transactional(readOnly=false)
396
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
397
    public UUID saveGrantedAuthority(GrantedAuthority grantedAuthority) {
398
        return grantedAuthorityDao.save((GrantedAuthorityImpl)grantedAuthority);
399
    }
400

    
401
    @Deprecated // use GroupService instead
402
    @Transactional(readOnly=false)
403
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
404
    public UUID saveGroup(Group group) {
405
        return groupDao.save(group);
406
    }
407

    
408
    /* (non-Javadoc)
409
     * @see eu.etaxonomy.cdm.api.service.IUserService#listByUsername(java.lang.String, eu.etaxonomy.cdm.persistence.query.MatchMode, java.util.List, java.lang.Integer, java.lang.Integer, java.util.List, java.util.List)
410
     */
411
    @Override
412
    @Transactional(readOnly = true)
413
    public List<User> listByUsername(String queryString,MatchMode matchmode, List<Criterion> criteria, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
414
         Integer numberOfResults = dao.countByUsername(queryString, matchmode, criteria);
415

    
416
         List<User> results = new ArrayList<User>();
417
         if(numberOfResults > 0) {
418
                results = dao.findByUsername(queryString, matchmode, criteria, pageSize, pageNumber, orderHints, propertyPaths);
419
         }
420
         return results;
421
    }
422

    
423
    /* ================================================
424
     *  overriding methods to secure them
425
     *  via the type level annotation @PreAuthorize
426
     * ================================================ */
427

    
428
    @Override
429
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
430
    public UUID delete(User persistentObject) {
431
        return super.delete(persistentObject);
432
    }
433

    
434
    @Override
435
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
436
    public Map<UUID, User> save(Collection<User> newInstances) {
437
        return super.save(newInstances);
438
    }
439

    
440
    @Override
441
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
442
    public UUID saveOrUpdate(User transientObject) {
443
        return super.saveOrUpdate(transientObject);
444
    }
445

    
446
    @Override
447
    @PreAuthorize("hasRole('ROLE_ADMIN') or hasRole('ROLE_USER_MANAGER')")
448
    public Map<UUID, User> saveOrUpdate(Collection<User> transientInstances) {
449
        return super.saveOrUpdate(transientInstances);
450
    }
451

    
452
}
(81-81/84)