Project

General

Profile

Download (10.3 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.util.EnumSet;
12

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

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

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

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

    
51
    public static final Logger logger = Logger.getLogger(CdmUserHelper.class);
52

    
53
    @Autowired
54
    private ICdmPermissionEvaluator permissionEvaluator;
55

    
56
    @Autowired
57
    @Qualifier("cdmRepository")
58
    private CdmRepository repo;
59

    
60
    AuthenticationProvider runAsAuthenticationProvider;
61

    
62
    @Autowired
63
    @Qualifier("runAsAuthenticationProvider")
64
    public void setRunAsAuthenticationProvider(AuthenticationProvider runAsAuthenticationProvider){
65
        this.runAsAuthenticationProvider = runAsAuthenticationProvider;
66
        runAsAutheticator.setRunAsAuthenticationProvider(runAsAuthenticationProvider);
67
    }
68

    
69
    RunAsAuthenticator runAsAutheticator = new RunAsAuthenticator();
70

    
71
    public CdmUserHelper(){
72
        super();
73
    }
74

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

    
84

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

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

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

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

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

    
137
    @Override
138
    public boolean userHasPermission(Class<? extends CdmBase> cdmType, Integer entitiyId, Object ... args){
139
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
140
        try {
141
            CdmBase entity = repo.getCommonService().find(cdmType, entitiyId);
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, Object ... args){
151
        EnumSet<CRUD> crudSet = crudSetFromArgs(args);
152
        try {
153
            return permissionEvaluator.hasPermission(getAuthentication(), cdmType, crudSet);
154
        } catch (PermissionDeniedException e){
155
            //IGNORE
156
        }
157
        return false;
158
    }
159

    
160
    public void logout() {
161
        SecurityContext context = SecurityContextHolder.getContext();
162
        context.setAuthentication(null);
163
        SecurityContextHolder.clearContext();
164
    }
165

    
166

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

    
179

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

    
189
    /**
190
     * @return
191
     */
192
    private Authentication getAuthentication() {
193
        return currentSecurityContext().getAuthentication();
194
    }
195

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

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

    
230
    }
231

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

    
242
        CdmBase cdmEntity = repo.getCommonService().find(cdmType, entitiyId);
243
        return createAuthorityFor(username, cdmEntity, crud, property);
244
    }
245

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

    
253
    }
254

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

    
266
    /**
267
     * {@inheritDoc}
268
     */
269
    @Override
270
    public void removeAuthorityForCurrentUser(CdmAuthority cdmAuthority) {
271
        removeAuthorityForCurrentUser(userName(), cdmAuthority);
272

    
273
    }
274

    
275
    /**
276
     * {@inheritDoc}
277
     */
278
    @Override
279
    public void removeAuthorityForCurrentUser(String username, CdmAuthority cdmAuthority) {
280

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

    
293
    }
294

    
295
}
(3-3/7)