Project

General

Profile

Download (10.6 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

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

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

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

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

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

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

    
56
    @Autowired
57
    private ICdmPermissionEvaluator permissionEvaluator;
58

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

    
63
    AuthenticationProvider runAsAuthenticationProvider;
64

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

    
72
    RunAsAuthenticator runAsAutheticator = new RunAsAuthenticator();
73

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

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

    
87

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

    
96
    @Override
97
    public String userName() {
98
        Authentication authentication = getAuthentication();
99
        if(authentication != null) {
100
            return authentication.getName();
101
        }
102
        return null;
103
    }
104

    
105
    @Override
106
    public boolean userIsAdmin() {
107
        Authentication authentication = getAuthentication();
108
        if(authentication != null) {
109
            return authentication.getAuthorities().stream().anyMatch(a -> {
110
                return a.getAuthority().equals(Role.ROLE_ADMIN.getAuthority());
111
            });
112
        }
113
        return false;
114
    }
115

    
116
    @Override
117
    public boolean userIsRegistrationCurator() {
118
        Authentication authentication = getAuthentication();
119
        if(authentication != null) {
120
            return authentication.getAuthorities().stream().anyMatch(a -> {
121
                return a.equals(RolesAndPermissions.ROLE_CURATION)
122
                        // doing faster regex check here instreas of using CdmAuthoritiy.fromString()
123
                        || a.getAuthority().matches("^Registration\\.\\[.*UPDATE");
124
            });
125
        }
126
        return false;
127
    }
128

    
129
    @Override
130
    public boolean userHasPermission(CdmBase entity, Object ... args){
131
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
132
        try {
133
            return permissionEvaluator.hasPermission(getAuthentication(), entity, crudSet);
134
        } catch (PermissionDeniedException e){
135
            //IGNORE
136
        }
137
        return false;
138
    }
139

    
140
    @Override
141
    public boolean userHasPermission(Class<? extends CdmBase> cdmType, Integer entitiyId, Object ... args){
142
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
143
        try {
144
            CdmBase entity = repo.getCommonService().find(cdmType, entitiyId);
145
            return permissionEvaluator.hasPermission(getAuthentication(), entity, crudSet);
146
        } catch (PermissionDeniedException e){
147
            //IGNORE
148
        }
149
        return false;
150
    }
151

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

    
163
    public void logout() {
164
        SecurityContext context = SecurityContextHolder.getContext();
165
        context.setAuthentication(null);
166
        SecurityContextHolder.clearContext();
167
    }
168

    
169

    
170
    private EnumSet<CRUD> crudSetFromArgs(Object[] args) {
171
        EnumSet<CRUD> crudSet = EnumSet.noneOf(CRUD.class);
172
        for(int i = 0; i < args.length; i++){
173
            try {
174
                crudSet.add(CRUD.valueOf(args[i].toString()));
175
            } catch (Exception e){
176
                throw new IllegalArgumentException("could not add " + args[i], e);
177
            }
178
        }
179
        return crudSet;
180
    }
181

    
182

    
183
    /**
184
     * @return
185
     *
186
     * FIXME is it ok to use the SecurityContextHolder or do we need to hold the context in the vaadin session?
187
     */
188
    private SecurityContext currentSecurityContext() {
189
        return SecurityContextHolder.getContext();
190
    }
191

    
192
    /**
193
     * @return
194
     */
195
    private Authentication getAuthentication() {
196
        return currentSecurityContext().getAuthentication();
197
    }
198

    
199
    /**
200
     * {@inheritDoc}
201
     *
202
     */
203
    @Override
204
    public CdmAuthority createAuthorityFor(String username, CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
205

    
206
        TransactionStatus txStatus = repo.startTransaction();
207
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
208
        boolean newAuthorityAdded = false;
209
        CdmAuthority authority = null;
210
        User user = (User)userDetails;
211
        if(userDetails != null){
212
            try{
213
                runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
214
                authority = new CdmAuthority(cdmEntity, property, crud);
215
                try {
216
                    GrantedAuthorityImpl grantedAuthority = repo.getGrantedAuthorityService().findAuthorityString(authority.toString());
217
                    if(grantedAuthority == null){
218
                        grantedAuthority = authority.asNewGrantedAuthority();
219
                    }
220
                    newAuthorityAdded = user.getGrantedAuthorities().add(grantedAuthority);
221
                } catch (CdmAuthorityParsingException e) {
222
                    throw new RuntimeException(e);
223
                }
224
                repo.getSession().flush();
225
            } finally {
226
                // in any case restore the previous authentication
227
                runAsAutheticator.restoreAuthentication();
228
            }
229
            logger.debug("new authority for " + username + ": " + authority.toString());
230
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
231
            SecurityContextHolder.getContext().setAuthentication(authentication);
232
            logger.debug("security context refreshed with user " + username);
233
        }
234
        repo.commitTransaction(txStatus);
235
        return newAuthorityAdded ? authority : null;
236

    
237
    }
238

    
239
    /**
240
     * @param username
241
     * @param cdmType
242
     * @param entitiyId
243
     * @param crud
244
     * @return
245
     */
246
    @Override
247
    public CdmAuthority createAuthorityFor(String username, Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
248

    
249
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
250
        return createAuthorityFor(username, cdmEntity, crud, property);
251
    }
252

    
253
    /**
254
     * {@inheritDoc}
255
     */
256
    @Override
257
    public CdmAuthority createAuthorityForCurrentUser(CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
258
        return createAuthorityFor(userName(), cdmEntity, crud, property);
259

    
260
    }
261

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

    
273
    /**
274
     * {@inheritDoc}
275
     */
276
    @Override
277
    public void removeAuthorityForCurrentUser(CdmAuthority cdmAuthority) {
278
        removeAuthorityForCurrentUser(userName(), cdmAuthority);
279

    
280
    }
281

    
282
    /**
283
     * {@inheritDoc}
284
     */
285
    @Override
286
    public void removeAuthorityForCurrentUser(String username, CdmAuthority cdmAuthority) {
287

    
288
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
289
        if(userDetails != null){
290
            runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
291
            User user = (User)userDetails;
292
            user.getGrantedAuthorities().remove(cdmAuthority);
293
            repo.getSession().flush();
294
            runAsAutheticator.restoreAuthentication();
295
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
296
            SecurityContextHolder.getContext().setAuthentication(authentication);
297
            logger.debug("security context refreshed with user " + username);
298
        }
299

    
300
    }
301

    
302
}
(3-3/7)