Project

General

Profile

Download (10.4 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
        if(userDetails != null){
211
            runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
212
            User user = (User)userDetails;
213
            authority = new CdmAuthority(cdmEntity, property, crud);
214
            try {
215
                GrantedAuthorityImpl grantedAuthority = repo.getGrantedAuthorityService().findAuthorityString(authority.toString());
216
                if(grantedAuthority == null){
217
                    grantedAuthority = authority.asNewGrantedAuthority();
218
                }
219
                newAuthorityAdded = user.getGrantedAuthorities().add(grantedAuthority);
220
            } catch (CdmAuthorityParsingException e) {
221
                throw new RuntimeException(e);
222
            }
223
            repo.getSession().flush();
224
            runAsAutheticator.restoreAuthentication();
225
            logger.debug("new authority for " + username + ": " + authority.toString());
226
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
227
            SecurityContextHolder.getContext().setAuthentication(authentication);
228
            logger.debug("security context refreshed with user " + username);
229
        }
230
        repo.commitTransaction(txStatus);
231
        return newAuthorityAdded ? authority : null;
232

    
233
    }
234

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

    
245
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
246
        return createAuthorityFor(username, cdmEntity, crud, property);
247
    }
248

    
249
    /**
250
     * {@inheritDoc}
251
     */
252
    @Override
253
    public CdmAuthority createAuthorityForCurrentUser(CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
254
        return createAuthorityFor(userName(), cdmEntity, crud, property);
255

    
256
    }
257

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

    
269
    /**
270
     * {@inheritDoc}
271
     */
272
    @Override
273
    public void removeAuthorityForCurrentUser(CdmAuthority cdmAuthority) {
274
        removeAuthorityForCurrentUser(userName(), cdmAuthority);
275

    
276
    }
277

    
278
    /**
279
     * {@inheritDoc}
280
     */
281
    @Override
282
    public void removeAuthorityForCurrentUser(String username, CdmAuthority cdmAuthority) {
283

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

    
296
    }
297

    
298
}
(3-3/7)