Project

General

Profile

Download (12.1 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2017 EDIT
3
* European Distributed Institute of Taxonomy
4
* http://www.e-taxonomy.eu
5
*
6
* The contents of this file are subject to the Mozilla Public License Version 1.1
7
* See LICENSE.TXT at the top of this package for the full license terms.
8
*/
9
package eu.etaxonomy.cdm.service;
10

    
11
import java.io.Serializable;
12
import java.util.EnumSet;
13
import java.util.UUID;
14

    
15
import org.apache.log4j.Logger;
16
import org.springframework.beans.factory.annotation.Autowired;
17
import org.springframework.beans.factory.annotation.Qualifier;
18
import org.springframework.security.authentication.AnonymousAuthenticationToken;
19
import org.springframework.security.authentication.AuthenticationProvider;
20
import org.springframework.security.core.Authentication;
21
import org.springframework.security.core.context.SecurityContext;
22
import org.springframework.security.core.context.SecurityContextHolder;
23
import org.springframework.security.core.userdetails.UserDetails;
24
import org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationToken;
25
import org.springframework.transaction.TransactionStatus;
26

    
27
import com.vaadin.spring.annotation.SpringComponent;
28
import com.vaadin.spring.annotation.UIScope;
29

    
30
import eu.etaxonomy.cdm.api.application.CdmRepository;
31
import eu.etaxonomy.cdm.api.application.RunAsAuthenticator;
32
import eu.etaxonomy.cdm.database.PermissionDeniedException;
33
import eu.etaxonomy.cdm.model.common.CdmBase;
34
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
35
import eu.etaxonomy.cdm.model.common.User;
36
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
37
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
38
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthorityParsingException;
39
import eu.etaxonomy.cdm.persistence.hibernate.permission.ICdmPermissionEvaluator;
40
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
41
import eu.etaxonomy.cdm.vaadin.security.RolesAndPermissions;
42
import eu.etaxonomy.cdm.vaadin.security.VaadinUserHelper;
43

    
44
/**
45
 * @author a.kohlbecker
46
 * @since May 19, 2017
47
 *
48
 */
49
@SpringComponent
50
@UIScope
51
public class CdmUserHelper extends VaadinUserHelper implements Serializable {
52

    
53
    private static final long serialVersionUID = -2521474709047255979L;
54

    
55
    public static final Logger logger = Logger.getLogger(CdmUserHelper.class);
56

    
57
    @Autowired
58
    private ICdmPermissionEvaluator permissionEvaluator;
59

    
60
    @Autowired
61
    @Qualifier("cdmRepository")
62
    private CdmRepository repo;
63

    
64
    AuthenticationProvider runAsAuthenticationProvider;
65

    
66
    @Autowired
67
    @Qualifier("runAsAuthenticationProvider")
68
    public void setRunAsAuthenticationProvider(AuthenticationProvider runAsAuthenticationProvider){
69
        this.runAsAuthenticationProvider = runAsAuthenticationProvider;
70
        runAsAutheticator.setRunAsAuthenticationProvider(runAsAuthenticationProvider);
71
    }
72

    
73
    RunAsAuthenticator runAsAutheticator = new RunAsAuthenticator();
74

    
75
    public CdmUserHelper(){
76
        super();
77
    }
78

    
79
    @Override
80
    public boolean userIsAutheticated() {
81
        Authentication authentication = getAuthentication();
82
        if(authentication != null){
83
            return authentication.isAuthenticated();
84
        }
85
        return false;
86
    }
87

    
88

    
89
    @Override
90
    public boolean userIsAnnonymous() {
91
        Authentication authentication = getAuthentication();
92
        return authentication != null
93
                && authentication.isAuthenticated()
94
                && authentication instanceof AnonymousAuthenticationToken;
95
    }
96

    
97
    @Override
98
    public User user() {
99
        Authentication authentication = getAuthentication();
100
        if(authentication != null && authentication.getPrincipal() != null) {
101
            return (User) authentication.getPrincipal();
102
        }
103
        return null;
104
    }
105

    
106
    @Override
107
    public String userName() {
108
        Authentication authentication = getAuthentication();
109
        if(authentication != null) {
110
            return authentication.getName();
111
        }
112
        return null;
113
    }
114

    
115
    @Override
116
    public boolean userIsAdmin() {
117
        Authentication authentication = getAuthentication();
118
        if(authentication != null) {
119
            return authentication.getAuthorities().stream().anyMatch(a -> {
120
                return a.getAuthority().equals(Role.ROLE_ADMIN.getAuthority());
121
            });
122
        }
123
        return false;
124
    }
125

    
126
    @Override
127
    public boolean userIsRegistrationCurator() {
128
        Authentication authentication = getAuthentication();
129
        if(authentication != null) {
130
            return authentication.getAuthorities().stream().anyMatch(a -> {
131
                return a.equals(RolesAndPermissions.ROLE_CURATION)
132
                        // doing faster regex check here instreas of using CdmAuthoritiy.fromString()
133
                        || a.getAuthority().matches("^Registration\\.\\[.*UPDATE");
134
            });
135
        }
136
        return false;
137
    }
138

    
139
    @Override
140
    public boolean userHasPermission(CdmBase entity, Object ... args){
141
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
142
        try {
143
            return permissionEvaluator.hasPermission(getAuthentication(), entity, crudSet);
144
        } catch (PermissionDeniedException e){
145
            //IGNORE
146
        }
147
        return false;
148
    }
149

    
150
    @Override
151
    public boolean userHasPermission(Class<? extends CdmBase> cdmType, Integer entitiyId, Object ... args){
152
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
153
        try {
154
            CdmBase entity = repo.getCommonService().find(cdmType, entitiyId);
155
            return permissionEvaluator.hasPermission(getAuthentication(), entity, crudSet);
156
        } catch (PermissionDeniedException e){
157
            //IGNORE
158
        }
159
        return false;
160
    }
161

    
162
    @Override
163
    public boolean userHasPermission(Class<? extends CdmBase> cdmType, UUID entitiyUuid, Object ... args){
164
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
165
        try {
166
            CdmBase entity = repo.getCommonService().find(cdmType, entitiyUuid);
167
            return permissionEvaluator.hasPermission(getAuthentication(), entity, crudSet);
168
        } catch (PermissionDeniedException e){
169
            //IGNORE
170
        }
171
        return false;
172
    }
173

    
174
    @Override
175
    public boolean userHasPermission(Class<? extends CdmBase> cdmType, Object ... args){
176
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
177
        try {
178
            return permissionEvaluator.hasPermission(getAuthentication(), cdmType, crudSet);
179
        } catch (PermissionDeniedException e){
180
            //IGNORE
181
        }
182
        return false;
183
    }
184

    
185
    public void logout() {
186
        SecurityContext context = SecurityContextHolder.getContext();
187
        context.setAuthentication(null);
188
        SecurityContextHolder.clearContext();
189
    }
190

    
191

    
192
    private EnumSet<CRUD> crudSetFromArgs(Object[] args) {
193
        EnumSet<CRUD> crudSet = EnumSet.noneOf(CRUD.class);
194
        for(int i = 0; i < args.length; i++){
195
            try {
196
                crudSet.add(CRUD.valueOf(args[i].toString()));
197
            } catch (Exception e){
198
                throw new IllegalArgumentException("could not add " + args[i], e);
199
            }
200
        }
201
        return crudSet;
202
    }
203

    
204

    
205
    /**
206
     * @return
207
     *
208
     * FIXME is it ok to use the SecurityContextHolder or do we need to hold the context in the vaadin session?
209
     */
210
    private SecurityContext currentSecurityContext() {
211
        return SecurityContextHolder.getContext();
212
    }
213

    
214
    /**
215
     * @return
216
     */
217
    private Authentication getAuthentication() {
218
        return currentSecurityContext().getAuthentication();
219
    }
220

    
221
    /**
222
     * {@inheritDoc}
223
     *
224
     */
225
    @Override
226
    public CdmAuthority createAuthorityFor(String username, CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
227

    
228
        TransactionStatus txStatus = repo.startTransaction();
229
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
230
        boolean newAuthorityAdded = false;
231
        CdmAuthority authority = null;
232
        User user = (User)userDetails;
233
        if(userDetails != null){
234
            try{
235
                runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
236
                authority = new CdmAuthority(cdmEntity, property, crud);
237
                try {
238
                    GrantedAuthorityImpl grantedAuthority = repo.getGrantedAuthorityService().findAuthorityString(authority.toString());
239
                    if(grantedAuthority == null){
240
                        grantedAuthority = authority.asNewGrantedAuthority();
241
                    }
242
                    newAuthorityAdded = user.getGrantedAuthorities().add(grantedAuthority);
243
                } catch (CdmAuthorityParsingException e) {
244
                    throw new RuntimeException(e);
245
                }
246
                repo.getSession().flush();
247
            } finally {
248
                // in any case restore the previous authentication
249
                runAsAutheticator.restoreAuthentication();
250
            }
251
            logger.debug("new authority for " + username + ": " + authority.toString());
252
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
253
            SecurityContextHolder.getContext().setAuthentication(authentication);
254
            logger.debug("security context refreshed with user " + username);
255
        }
256
        repo.commitTransaction(txStatus);
257
        return newAuthorityAdded ? authority : null;
258

    
259
    }
260

    
261
    /**
262
     * @param username
263
     * @param cdmType
264
     * @param entitiyId
265
     * @param crud
266
     * @return
267
     */
268
    @Override
269
    public CdmAuthority createAuthorityFor(String username, Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
270

    
271
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
272
        return createAuthorityFor(username, cdmEntity, crud, property);
273
    }
274

    
275
    /**
276
     * @param username
277
     * @param cdmType
278
     * @param entitiyUuid
279
     * @param crud
280
     * @return
281
     */
282
    @Override
283
    public CdmAuthority createAuthorityFor(String username, Class<? extends CdmBase> cdmType, UUID entitiyUuid, EnumSet<CRUD> crud, String property) {
284

    
285
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyUuid);
286
        return createAuthorityFor(username, cdmEntity, crud, property);
287
    }
288

    
289
    /**
290
     * {@inheritDoc}
291
     */
292
    @Override
293
    public CdmAuthority createAuthorityForCurrentUser(CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
294
        return createAuthorityFor(userName(), cdmEntity, crud, property);
295

    
296
    }
297

    
298
    /**
299
     * @param cdmType
300
     * @param entitiyId
301
     * @param crud
302
     * @return
303
     */
304
    @Override
305
    public CdmAuthority createAuthorityForCurrentUser(Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
306
        return createAuthorityFor(userName(), cdmType, entitiyId, crud, property);
307
    }
308

    
309
    /**
310
     * @param cdmType
311
     * @param entitiyUuid
312
     * @param crud
313
     * @return
314
     */
315
    @Override
316
    public CdmAuthority createAuthorityForCurrentUser(Class<? extends CdmBase> cdmType, UUID entitiyUuid, EnumSet<CRUD> crud, String property) {
317
        return createAuthorityFor(userName(), cdmType, entitiyUuid, crud, property);
318
    }
319

    
320
    /**
321
     * {@inheritDoc}
322
     */
323
    @Override
324
    public void removeAuthorityForCurrentUser(CdmAuthority cdmAuthority) {
325
        removeAuthorityForCurrentUser(userName(), cdmAuthority);
326

    
327
    }
328

    
329
    /**
330
     * {@inheritDoc}
331
     */
332
    @Override
333
    public void removeAuthorityForCurrentUser(String username, CdmAuthority cdmAuthority) {
334

    
335
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
336
        if(userDetails != null){
337
            runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
338
            User user = (User)userDetails;
339
            user.getGrantedAuthorities().remove(cdmAuthority);
340
            repo.getSession().flush();
341
            runAsAutheticator.restoreAuthentication();
342
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
343
            SecurityContextHolder.getContext().setAuthentication(authentication);
344
            logger.debug("security context refreshed with user " + username);
345
        }
346

    
347
    }
348

    
349
}
(3-3/7)