Project

General

Profile

Download (11.5 KB) Statistics
| Branch: | Tag: | Revision:
1
/**
2
* Copyright (C) 2012 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.api.application;
10

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

    
18
import org.apache.log4j.Logger;
19
import org.springframework.beans.factory.annotation.Autowired;
20
import org.springframework.context.event.ContextRefreshedEvent;
21
import org.springframework.context.event.ContextStartedEvent;
22
import org.springframework.security.authentication.AuthenticationProvider;
23
import org.springframework.security.core.GrantedAuthority;
24
import org.springframework.transaction.PlatformTransactionManager;
25
import org.springframework.transaction.TransactionDefinition;
26
import org.springframework.transaction.TransactionStatus;
27
import org.springframework.transaction.support.DefaultTransactionDefinition;
28

    
29
import eu.etaxonomy.cdm.api.service.ICommonService;
30
import eu.etaxonomy.cdm.api.service.IGrantedAuthorityService;
31
import eu.etaxonomy.cdm.api.service.IGroupService;
32
import eu.etaxonomy.cdm.api.service.IUserService;
33
import eu.etaxonomy.cdm.common.monitor.IProgressMonitor;
34
import eu.etaxonomy.cdm.common.monitor.NullProgressMonitor;
35
import eu.etaxonomy.cdm.config.Configuration;
36
import eu.etaxonomy.cdm.model.common.GrantedAuthorityImpl;
37
import eu.etaxonomy.cdm.model.common.Group;
38
import eu.etaxonomy.cdm.model.common.User;
39
import eu.etaxonomy.cdm.model.metadata.CdmMetaData;
40
import eu.etaxonomy.cdm.persistence.hibernate.permission.CRUD;
41
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmAuthority;
42
import eu.etaxonomy.cdm.persistence.hibernate.permission.CdmPermissionClass;
43
import eu.etaxonomy.cdm.persistence.hibernate.permission.Role;
44
import eu.etaxonomy.cdm.persistence.query.OrderHint;
45

    
46
/**
47
 * The <code>FirstDataInserter</code> is responsible for equipping a new and empty database with
48
 * the initial set of data need by the cdmlib. It operates not only on empty databases,
49
 * its methods are executed everytime the ApplicationContext has been started up, that is listens
50
 * for {@link ContextStartedEvent}s.
51
 * <p>
52
 * responsibilities:
53
 * <ul>
54
 * <li>User 'admin' and role 'ROLE_ADMIN'</li>
55
 * <li>cdm metadata</li>
56
 * <ul>
57
 * <p>
58
 * The <code>runAsAuthenticationProvider</code> must be set in a security application context, eg:
59
 * {@code
60
    <bean id="firstDataInserter" class="eu.etaxonomy.cdm.api.application.FirstDataInserter">
61
        <property name="runAsAuthenticationProvider" ref="runAsAuthenticationProvider"/>
62
    </bean>
63
    }
64
 *
65
 *
66
 *
67
 * @author a.kohlbecker
68
 * @date Oct 12, 2012
69
 *
70
 */
71
//@RunAs("ROLE_ADMIN") // seems to be broken in spring see: https://jira.springsource.org/browse/SEC-1671
72
public class FirstDataInserter extends AbstractDataInserter {
73

    
74
    /**
75
     *
76
     */
77
    private static final EnumSet<CRUD> CREATE_READ = EnumSet.of(CRUD.CREATE, CRUD.READ);
78
    private static final EnumSet<CRUD> UPDATE_DELETE = EnumSet.of(CRUD.UPDATE, CRUD.DELETE);
79
    private static final EnumSet<CRUD> CREATE_READ_UPDATE = EnumSet.of(CRUD.CREATE, CRUD.READ, CRUD.UPDATE);
80
    private static final EnumSet<CRUD> CREATE_READ_UPDATE_DELETE = EnumSet.of(CRUD.CREATE, CRUD.READ, CRUD.UPDATE, CRUD.DELETE);
81

    
82
    public static final Logger logger = Logger.getLogger(FirstDataInserter.class);
83

    
84
    public static final String[] EDITOR_GROUP_AUTHORITIES = new String[]{
85
            new CdmAuthority(CdmPermissionClass.REFERENCE, CREATE_READ).toString(),
86
            new CdmAuthority(CdmPermissionClass.TAXONNAME, CREATE_READ_UPDATE).toString(),
87
            new CdmAuthority(CdmPermissionClass.TEAMORPERSONBASE, CREATE_READ).toString(),
88
            new CdmAuthority(CdmPermissionClass.TAXONBASE, CREATE_READ_UPDATE_DELETE).toString(),
89
            new CdmAuthority(CdmPermissionClass.DESCRIPTIONBASE, CREATE_READ_UPDATE_DELETE).toString(),
90
            new CdmAuthority(CdmPermissionClass.DESCRIPTIONELEMENTBASE, CREATE_READ_UPDATE_DELETE).toString(),
91
            new CdmAuthority(CdmPermissionClass.TYPEDESIGNATIONBASE, CREATE_READ_UPDATE_DELETE).toString(),
92
    };
93

    
94
    public static final String[] PROJECT_MANAGER_GROUP_AUTHORITIES = new String[]{
95
            new CdmAuthority(CdmPermissionClass.REFERENCE, UPDATE_DELETE).toString(),
96
            new CdmAuthority(CdmPermissionClass.TAXONNAME, EnumSet.of(CRUD.DELETE)).toString(),
97
            new CdmAuthority(CdmPermissionClass.TEAMORPERSONBASE, UPDATE_DELETE).toString(),
98
            Role.ROLE_PROJECT_MANAGER.toString(),
99
    };
100

    
101
    public static final String[] ADMIN_GROUP_AUTHORITIES = new String[]{
102
            Role.ROLE_ADMIN.toString()
103
    };
104

    
105
    @Autowired
106
    private ICommonService commonService;
107

    
108
    @Autowired
109
    private IUserService userService;
110

    
111
    @Autowired
112
    private IGroupService groupService;
113

    
114

    
115
    @Autowired
116
    private IGrantedAuthorityService grantedAuthorityService;
117

    
118
    // not to be autowired, since the FirstdataInserter must be usable without security
119
    private AuthenticationProvider runAsAuthenticationProvider = null;
120

    
121
    protected PlatformTransactionManager transactionManager;
122

    
123
    protected DefaultTransactionDefinition txDefinition = new DefaultTransactionDefinition();
124

    
125
    private IProgressMonitor progressMonitor = null;
126

    
127
    private boolean firstDataInserted = false;
128

    
129
    @Autowired
130
    public void setTransactionManager(PlatformTransactionManager transactionManager) {
131
        this.transactionManager = transactionManager;
132
    }
133

    
134
    public FirstDataInserter() {
135
        txDefinition.setName("FirstDataInserter.insertFirstData()");
136
        txDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
137
    }
138

    
139
    @Override
140
    public void onApplicationEvent(ContextRefreshedEvent event) {
141
        if(event.getApplicationContext() instanceof MonitoredGenericApplicationContext){
142
            progressMonitor = ((MonitoredGenericApplicationContext)event.getApplicationContext()).getCurrentMonitor();
143
            /* TODO set up work amount, currently the amount of work ticks is hard coded
144
             *      in {@link CdmApplicationControllersetNewDataSource}, but we need some means to register
145
             *      additional ticks.
146
             *      see http://dev.e-taxonomy.eu/trac/ticket/3140 (generic way to obtain work ticks of application startup for monitoring)
147
             *
148
             */
149
        } else {
150
            progressMonitor = new NullProgressMonitor();
151
        }
152

    
153
        insertFirstData();
154
    }
155

    
156

    
157
    private void insertFirstData() {
158

    
159
        // this ApplicationListener may be called multiple times in nested
160
        // application contexts like in web applications
161
        if(!firstDataInserted){
162

    
163
            runAsAuthentication(Role.ROLE_ADMIN);
164

    
165
            TransactionStatus txStatus = transactionManager.getTransaction(txDefinition);
166

    
167
            logger.info("inserting first data");
168
            checkAdminUser();
169
            checkDefaultGroups();
170
            checkMetadata();
171
            firstDataInserted = true;
172

    
173
            transactionManager.commit(txStatus);
174

    
175
            restoreAuthentication();
176

    
177
        } else {
178
            logger.debug("insertFirstData() already executed before, skipping this time");
179
        }
180
    }
181

    
182

    
183
    private void checkMetadata() {
184
        int metaDataCount = commonService.getCdmMetaData().size();
185
        if (metaDataCount == 0){
186
            progressMonitor.subTask("Creating Meta Data");
187
            createMetadata();
188
        }
189
    }
190

    
191
    private void checkAdminUser() {
192
        User admin = findFirstUser();
193

    
194
        if (admin == null){
195
            progressMonitor.subTask("Creating Admin User");
196
            admin = createAdminUser();
197
        } else {
198
            logger.info("Assuming first user '" + admin + "' is admin.");
199
        }
200

    
201
        checkAdminRole(admin);
202
        progressMonitor.worked(1);
203
    }
204

    
205
    private void checkDefaultGroups(){
206

    
207
        progressMonitor.subTask("Checking default groups");
208
        checkGroup(Group.GROUP_EDITOR_UUID, "Editor", EDITOR_GROUP_AUTHORITIES);
209
        checkGroup(Group.GROUP_PROJECT_MANAGER_UUID, "ProjectManager", PROJECT_MANAGER_GROUP_AUTHORITIES);
210
        checkGroup(Group.GROUP_ADMIN_UUID, "Admin", ADMIN_GROUP_AUTHORITIES);
211
        progressMonitor.worked(1);
212
    }
213

    
214
    /**
215
     * @param newGroups
216
     * @param groupName
217
     * @param requiredAuthorities
218
     */
219
    private void checkGroup(UUID groupUuid, String groupName, String[] requiredAuthorities) {
220
        Group group = groupService.load(groupUuid);
221
        if(group == null){
222
            group = Group.NewInstance();
223
            group.setUuid(groupUuid);
224
            logger.info("New Group '" + groupName + "' created");
225
        }
226
        group.setName(groupName); // force name
227

    
228
        Set<GrantedAuthority> grantedAuthorities = group.getGrantedAuthorities();
229

    
230
        for(String a : requiredAuthorities){
231
            boolean isMissing = true;
232
            for(GrantedAuthority ga : grantedAuthorities){
233
                if(a.equals(ga.getAuthority())){
234
                    isMissing = false;
235
                    break;
236
                }
237
            }
238
            if(isMissing){
239
                GrantedAuthorityImpl newGa = grantedAuthorityService.findAuthorityString(a);
240

    
241
                if (newGa == null){
242
                    newGa = GrantedAuthorityImpl.NewInstance(a);
243
                }
244

    
245
                group.addGrantedAuthority(newGa);
246
                logger.info("New GrantedAuthority '" + a + "' added  to '" + groupName + "'");
247
            }
248
        }
249

    
250
        groupService.merge(group, true);
251
        logger.info("Check of group  '" + groupName + "' done");
252
    }
253

    
254
    /**
255
     * @return
256
     */
257
    private User findFirstUser() {
258
        User firstUser = null;
259
        List<User> users = userService.list(null, 1, null, Arrays.asList(new OrderHint[]{new OrderHint("id", OrderHint.SortOrder.ASCENDING)}), null);
260
        if(users.size() > 0){
261
            firstUser = users.get(0);
262
        }
263
        return firstUser;
264
    }
265

    
266
    private User createAdminUser(){
267

    
268
        User admin = User.NewInstance(Configuration.adminLogin, Configuration.adminPassword);
269
        userService.save(admin);
270
        logger.info("user '" + Configuration.adminLogin + "' created.");
271
        return admin;
272
    }
273

    
274
    private void checkAdminRole(User admin) {
275
        Set<GrantedAuthority> authorities = new HashSet<GrantedAuthority>();
276

    
277

    
278
        authorities = (Set<GrantedAuthority>) admin.getAuthorities();
279

    
280
        boolean hasRoleAdmin = false;
281
        for(GrantedAuthority grau : authorities){
282
            if(grau.getAuthority().contentEquals(Role.ROLE_ADMIN.getAuthority())){
283
                hasRoleAdmin = true;
284
                break;
285
            }
286
        }
287

    
288
        if(!hasRoleAdmin){
289
            authorities.add(getRoleAdmin());
290
            admin.setGrantedAuthorities(authorities);
291
            progressMonitor.subTask("Creating Admins Role");
292
            userService.saveOrUpdate(admin);
293
            logger.info("Role " + Role.ROLE_ADMIN.getAuthority() + " for user '" + Configuration.adminLogin + "' created and added");
294
        }
295
    }
296

    
297
    /**
298
     * @return
299
     */
300
    private GrantedAuthorityImpl getRoleAdmin() {
301
        GrantedAuthorityImpl role_admin = grantedAuthorityService.find(Role.ROLE_ADMIN.getUuid());
302
        if(role_admin == null){
303
            role_admin = Role.ROLE_ADMIN.asNewGrantedAuthority();
304
        }
305
        return role_admin;
306
    }
307

    
308
    private void createMetadata(){
309
        List<CdmMetaData> metaData = CdmMetaData.defaultMetaData();
310
        commonService.saveAllMetaData(metaData);
311
        logger.info("Metadata created.");
312
    }
313

    
314
}
(5-5/9)