Project

General

Profile

Download (9.56 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.persistence.hibernate;
10

    
11
import java.util.ArrayList;
12
import java.util.Collection;
13
import java.util.EnumSet;
14
import java.util.HashSet;
15
import java.util.List;
16
import java.util.Set;
17

    
18
import org.hibernate.FlushMode;
19
import org.hibernate.Query;
20
import org.hibernate.event.spi.EventSource;
21
import org.hibernate.event.spi.PostUpdateEvent;
22
import org.hibernate.event.spi.PostUpdateEventListener;
23
import org.hibernate.persister.entity.EntityPersister;
24

    
25
import eu.etaxonomy.cdm.hibernate.HibernateProxyHelper;
26
import eu.etaxonomy.cdm.model.agent.AgentBase;
27
import eu.etaxonomy.cdm.model.agent.Person;
28
import eu.etaxonomy.cdm.model.agent.Team;
29
import eu.etaxonomy.cdm.model.agent.TeamOrPersonBase;
30
import eu.etaxonomy.cdm.model.name.Registration;
31
import eu.etaxonomy.cdm.model.name.RegistrationStatus;
32
import eu.etaxonomy.cdm.model.name.SpecimenTypeDesignation;
33
import eu.etaxonomy.cdm.model.name.TaxonName;
34
import eu.etaxonomy.cdm.model.name.TypeDesignationBase;
35
import eu.etaxonomy.cdm.model.occurrence.DerivedUnit;
36
import eu.etaxonomy.cdm.model.occurrence.FieldUnit;
37
import eu.etaxonomy.cdm.model.occurrence.SpecimenOrObservationBase;
38
import eu.etaxonomy.cdm.model.reference.Reference;
39
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
40
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
41

    
42
/**
43
 * @author a.kohlbecker
44
 * @since Dec 18, 2017
45
 *
46
 */
47
public class GrantedAuthorityRevokingRegistrationUpdateLister implements PostUpdateEventListener {
48

    
49
    private static final long serialVersionUID = -3542204523291766866L;
50

    
51
    /**
52
     *
53
     * Registrations having these states must no longer be midifiable by users having only per entity permissions on the
54
     * Registration subgraph
55
     */
56
    private static final EnumSet<RegistrationStatus> MODIFICATION_STOP_STATES = EnumSet.of(
57
            RegistrationStatus.PUBLISHED,
58
            RegistrationStatus.READY,
59
            RegistrationStatus.REJECTED
60
            );
61

    
62
    private static final EnumSet<CRUD> UPDATE_DELETE = EnumSet.of(CRUD.UPDATE, CRUD.DELETE);
63

    
64
    private static final EnumSet<CRUD> UPDATE = EnumSet.of(CRUD.UPDATE);
65

    
66
    /**
67
     * {@inheritDoc}
68
     */
69
    @Override
70
    public void onPostUpdate(PostUpdateEvent event) {
71
        if( event.getEntity() instanceof Registration){
72
            Registration reg = (Registration)event.getEntity();
73
            if(reg.getStatus() != null && MODIFICATION_STOP_STATES.contains(reg.getStatus())){
74
                Set<CdmAuthority> deleteCandidates = collectDeleteCandidates(reg);
75
                deleteAuthorities(event.getSession(), deleteCandidates);
76
            }
77
        }
78
    }
79

    
80
    /**
81
     * Walks the entity graph of the Registration instance and collects all authorities which
82
     * could have been granted to users. Code parts in which this could have happened can be
83
     * found by searching for usage of the methods {@link eu.etaxonomy.cdm.vaadin.security.UserHelper#createAuthorityForCurrentUser(eu.etaxonomy.cdm.model.common.CdmBase, EnumSet, String)
84
     * UserHelper.createAuthorityForCurrentUser(eu.etaxonomy.cdm.model.common.CdmBase, EnumSet, String)} and {@link eu.etaxonomy.cdm.vaadin.security.UserHelper#createAuthorityForCurrentUser(Class, Integer, EnumSet, String)
85
     * UserHelper.createAuthorityForCurrentUser(Class, Integer, EnumSet, String)}
86
     * <p>
87
     * At the time of implementing this function these places are:
88
     * <ul>
89
     *  <li><code>RegistrationEditorPresenter.guaranteePerEntityCRUDPermissions(...)</code></li>
90
     *  <li><code>RegistrationWorkingsetPresenter.createNewRegistrationForName(Integer taxonNameId)</code></li>
91
     *  <li><code>TaxonNameEditorPresenter.guaranteePerEntityCRUDPermissions(...)</code></li>
92
     *  <li><code>ReferenceEditorPresenter.guaranteePerEntityCRUDPermissions(...)</code></li>
93
     *  <li><code>PersonField.commit()</code></li>
94
     *  <li><code>TeamOrPersonField.commit()</code></li>
95
     *  <li><code>SpecimenTypeDesignationWorkingsetEditorPresenter.saveBean(SpecimenTypeDesignationWorkingSetDTO dto)</code></li>
96
     * </ul>
97
     *
98
     * @param reg the Registration
99
     * @return the set of all possible CdmAuthorities that could have been granted to
100
     * individual users.
101
     */
102
    private Set<CdmAuthority> collectDeleteCandidates(Registration reg){
103
        Set<CdmAuthority> deleteCandidates = new HashSet<CdmAuthority>();
104
        // add authority for Registration
105
        deleteCandidates.add(new CdmAuthority(reg,  RegistrationStatus.PREPARATION.name(), UPDATE));
106
        if(reg.getName() != null){
107
            addDeleteCandidates(deleteCandidates, reg.getName());
108
        }
109
        for(TypeDesignationBase td : reg.getTypeDesignations()){
110
            addDeleteCandidates(deleteCandidates, td);
111
        }
112

    
113
        return deleteCandidates;
114

    
115
    }
116

    
117
    /**
118
     * @param deleteCandidates
119
     * @param name
120
     */
121
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, TaxonName name) {
122
        if(name == null){
123
            return;
124
        }
125
        name = HibernateProxyHelper.deproxy(name);
126
        deleteCandidates.add(new CdmAuthority(name, UPDATE_DELETE));
127
        addDeleteCandidates(deleteCandidates, (Reference)name.getNomenclaturalReference());
128
        addDeleteCandidates(deleteCandidates, name.getCombinationAuthorship());
129
        addDeleteCandidates(deleteCandidates, name.getExCombinationAuthorship());
130
        addDeleteCandidates(deleteCandidates, name.getBasionymAuthorship());
131
        addDeleteCandidates(deleteCandidates, name.getExBasionymAuthorship());
132
    }
133

    
134

    
135
    /**
136
     * @param deleteCandidates
137
     * @param td
138
     */
139
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, TypeDesignationBase td) {
140
        if(td == null){
141
            return;
142
        }
143
        td = HibernateProxyHelper.deproxy(td);
144
        deleteCandidates.add(new CdmAuthority(td, UPDATE_DELETE));
145
        addDeleteCandidates(deleteCandidates, td.getCitation());
146
        if(td instanceof SpecimenTypeDesignation){
147
            SpecimenTypeDesignation std = (SpecimenTypeDesignation)td;
148
            addDeleteCandidates(deleteCandidates, std.getTypeSpecimen());
149
        }
150
    }
151

    
152
    /**
153
     * @param deleteCandidates
154
     * @param typeSpecimen
155
     */
156
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, DerivedUnit deriveUnit) {
157
        if(deriveUnit == null){
158
            return;
159
        }
160

    
161
        deriveUnit = HibernateProxyHelper.deproxy(deriveUnit);
162
        if(deriveUnit.getCollection() != null){
163
            deleteCandidates.add(new CdmAuthority(deriveUnit.getCollection(), UPDATE_DELETE));
164
        }
165
        for(SpecimenOrObservationBase sob : deriveUnit.getOriginals()){
166
            if(sob == null){
167
                continue;
168
            }
169
            deleteCandidates.add(new CdmAuthority(sob, UPDATE_DELETE));
170
            if(sob instanceof FieldUnit){
171
                addDeleteCandidates(deleteCandidates, (FieldUnit)sob);
172
            } else {
173
                addDeleteCandidates(deleteCandidates, (DerivedUnit)sob);
174
            }
175
        }
176
    }
177

    
178
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, FieldUnit fieldUnit) {
179
        if(fieldUnit == null){
180
            return;
181
        }
182
        fieldUnit = HibernateProxyHelper.deproxy(fieldUnit);
183
        if(fieldUnit.getGatheringEvent() != null){
184
            addDeleteCandidates(deleteCandidates, fieldUnit.getGatheringEvent().getActor());
185
        }
186
    }
187

    
188
    /**
189
     * @param deleteCandidates
190
     * @param nomenclaturalReference
191
     */
192
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, Reference reference) {
193
        if(reference == null){
194
            return;
195
        }
196
        reference = HibernateProxyHelper.deproxy(reference);
197
        deleteCandidates.add(new CdmAuthority(reference, UPDATE_DELETE));
198
        addDeleteCandidates(deleteCandidates, reference.getAuthorship());
199
        addDeleteCandidates(deleteCandidates, reference.getInReference());
200
    }
201

    
202
    private void addDeleteCandidates(Set<CdmAuthority> deleteCandidates, AgentBase<?> agent) {
203
        if(agent == null){
204
            return;
205
        }
206
        agent = HibernateProxyHelper.deproxy(agent);
207
        deleteCandidates.add(new CdmAuthority(agent, UPDATE_DELETE));
208
        if(agent instanceof TeamOrPersonBase){
209
            if(agent instanceof Team){
210
                List<Person> members = ((Team)agent).getTeamMembers();
211
                if(members != null){
212
                    for(Person p : members){
213
                        if(p != null){
214
                            deleteCandidates.add(new CdmAuthority(p, UPDATE_DELETE));
215
                        }
216
                    }
217
                }
218
            }
219
        }
220

    
221
    }
222

    
223

    
224

    
225

    
226
    /**
227
     * @param deleteCandidates
228
     */
229
    private void deleteAuthorities(EventSource session, Set<CdmAuthority> deleteCandidates) {
230

    
231
        Collection<String> authorityStrings = new ArrayList<String>(deleteCandidates.size());
232
        deleteCandidates.forEach( dc -> authorityStrings.add(dc.toString()));
233

    
234
        String hql = "delete from GrantedAuthorityImpl as ga where ga.authority in (:authorities)";
235
        Query query = session.createQuery(hql);
236
        query.setParameterList("authorities", authorityStrings);
237
        query.setFlushMode(FlushMode.MANUAL); // workaround for  HHH-11822 (https://hibernate.atlassian.net/browse/HHH-11822)
238
        query.executeUpdate();
239

    
240
    }
241

    
242
    @Override
243
    public boolean requiresPostCommitHanding(EntityPersister persister) {
244
        return false;
245
    }
246

    
247
}
    (1-1/1)