Project

General

Profile

Download (10.8 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 User user() {
98
        Authentication authentication = getAuthentication();
99
        if(authentication != null && authentication.getPrincipal() != null) {
100
            return (User) authentication.getPrincipal();
101
        }
102
        return null;
103
    }
104

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

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

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

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

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

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

    
172
    public void logout() {
173
        SecurityContext context = SecurityContextHolder.getContext();
174
        context.setAuthentication(null);
175
        SecurityContextHolder.clearContext();
176
    }
177

    
178

    
179
    private EnumSet<CRUD> crudSetFromArgs(Object[] args) {
180
        EnumSet<CRUD> crudSet = EnumSet.noneOf(CRUD.class);
181
        for(int i = 0; i < args.length; i++){
182
            try {
183
                crudSet.add(CRUD.valueOf(args[i].toString()));
184
            } catch (Exception e){
185
                throw new IllegalArgumentException("could not add " + args[i], e);
186
            }
187
        }
188
        return crudSet;
189
    }
190

    
191

    
192
    /**
193
     * @return
194
     *
195
     * FIXME is it ok to use the SecurityContextHolder or do we need to hold the context in the vaadin session?
196
     */
197
    private SecurityContext currentSecurityContext() {
198
        return SecurityContextHolder.getContext();
199
    }
200

    
201
    /**
202
     * @return
203
     */
204
    private Authentication getAuthentication() {
205
        return currentSecurityContext().getAuthentication();
206
    }
207

    
208
    /**
209
     * {@inheritDoc}
210
     *
211
     */
212
    @Override
213
    public CdmAuthority createAuthorityFor(String username, CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
214

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

    
246
    }
247

    
248
    /**
249
     * @param username
250
     * @param cdmType
251
     * @param entitiyId
252
     * @param crud
253
     * @return
254
     */
255
    @Override
256
    public CdmAuthority createAuthorityFor(String username, Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
257

    
258
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
259
        return createAuthorityFor(username, cdmEntity, crud, property);
260
    }
261

    
262
    /**
263
     * {@inheritDoc}
264
     */
265
    @Override
266
    public CdmAuthority createAuthorityForCurrentUser(CdmBase cdmEntity, EnumSet<CRUD> crud, String property) {
267
        return createAuthorityFor(userName(), cdmEntity, crud, property);
268

    
269
    }
270

    
271
    /**
272
     * @param cdmType
273
     * @param entitiyId
274
     * @param crud
275
     * @return
276
     */
277
    @Override
278
    public CdmAuthority createAuthorityForCurrentUser(Class<? extends CdmBase> cdmType, Integer entitiyId, EnumSet<CRUD> crud, String property) {
279
        return createAuthorityFor(userName(), cdmType, entitiyId, crud, property);
280
    }
281

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

    
289
    }
290

    
291
    /**
292
     * {@inheritDoc}
293
     */
294
    @Override
295
    public void removeAuthorityForCurrentUser(String username, CdmAuthority cdmAuthority) {
296

    
297
        UserDetails userDetails = repo.getUserService().loadUserByUsername(username);
298
        if(userDetails != null){
299
            runAsAutheticator.runAsAuthentication(Role.ROLE_USER_MANAGER);
300
            User user = (User)userDetails;
301
            user.getGrantedAuthorities().remove(cdmAuthority);
302
            repo.getSession().flush();
303
            runAsAutheticator.restoreAuthentication();
304
            Authentication authentication = new PreAuthenticatedAuthenticationToken(user, user.getPassword(), user.getAuthorities());
305
            SecurityContextHolder.getContext().setAuthentication(authentication);
306
            logger.debug("security context refreshed with user " + username);
307
        }
308

    
309
    }
310

    
311
}
(3-3/7)