]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
af74c698ed06fd778c6ad9a2caa3c4bdb3c3073a
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.authorization.driver;
25
26 import java.io.File;
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30
31 import javax.persistence.EntityManager;
32 import javax.persistence.EntityManagerFactory;
33
34 import org.collectionspace.services.authorization.AuthZ;
35 import org.collectionspace.services.authorization.perms.Permission;
36 import org.collectionspace.services.authorization.PermissionRole;
37 import org.collectionspace.services.authorization.PermissionRoleRel;
38 import org.collectionspace.services.authorization.Role;
39 import org.collectionspace.services.authorization.SubjectType;
40 import org.collectionspace.services.authorization.importer.AuthorizationGen;
41 import org.collectionspace.services.authorization.importer.AuthorizationSeed;
42 import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;
43 import org.collectionspace.services.common.authorization_mgt.PermissionRoleUtil;
44 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
45
46 import org.hibernate.exception.ConstraintViolationException;
47
48 import org.slf4j.Logger;
49 import org.slf4j.LoggerFactory;
50
51 import org.springframework.context.support.ClassPathXmlApplicationContext;
52 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
53 import org.springframework.security.core.Authentication;
54 import org.springframework.security.core.GrantedAuthority;
55 import org.springframework.security.core.authority.GrantedAuthorityImpl;
56 import org.springframework.security.core.context.SecurityContextHolder;
57 import org.springframework.transaction.TransactionDefinition;
58 import org.springframework.transaction.TransactionStatus;
59 import org.springframework.transaction.support.DefaultTransactionDefinition;
60
61 /**
62  * A driver for seeding authorization
63  * @author 
64  */
65 public class AuthorizationSeedDriver {
66
67     final Logger logger = LoggerFactory.getLogger(AuthorizationSeedDriver.class);
68     final static private String SPRING_SECURITY_METADATA = "applicationContext-authorization-test.xml";
69     final static private String ROLE_FILE = "import-roles.xml";
70     final static private String PERMISSION_FILE = "import-permissions.xml";
71     final static private String PERMISSION_ROLE_FILE = "import-permissions-roles.xml";
72     private String user;
73     private String password;
74     private String tenantBindingFile;
75     private String exportDir;
76     private AuthorizationGen authzGen;
77     private org.springframework.jdbc.datasource.DataSourceTransactionManager txManager;
78
79     /**
80      * AuthorizationSeedDriver
81      * @param user to use to establish security context. should be in ROLE_ADMINISTRATOR
82      * @param password
83      * @param tenantBindingFile
84      * @param importDir dir to import permisison/permission role file from. same as
85      * export dir by default
86      * @param exportDir dir to export permission/permission role file to
87      */
88     public AuthorizationSeedDriver(String user, String password,
89             String tenantBindingFile,
90             String exportDir) {
91         if (user == null || user.isEmpty()) {
92             throw new IllegalArgumentException("username required.");
93         }
94         this.user = user;
95
96         if (password == null || password.isEmpty()) {
97             throw new IllegalArgumentException("password required.");
98         }
99         this.password = password;
100         
101         if (tenantBindingFile == null || tenantBindingFile.isEmpty()) {
102             throw new IllegalArgumentException("tenantbinding file are required.");
103         }
104         this.tenantBindingFile = tenantBindingFile;
105         if (exportDir == null || exportDir.isEmpty()) {
106             throw new IllegalArgumentException("exportdir required.");
107         }
108         this.exportDir = exportDir;
109
110     }
111
112     public void generate() {
113         try {
114             authzGen = new AuthorizationGen();
115             authzGen.initialize(tenantBindingFile);
116             authzGen.createDefaultRoles();
117             authzGen.createDefaultPermissions();
118             authzGen.associateDefaultPermissionsRoles();
119             authzGen.exportDefaultRoles(exportDir + File.separator + ROLE_FILE);
120             authzGen.exportDefaultPermissions(exportDir + File.separator + PERMISSION_FILE);
121             authzGen.exportDefaultPermissionRoles(exportDir + File.separator + PERMISSION_ROLE_FILE);
122             if (logger.isDebugEnabled()) {
123                 logger.debug("Authorization generation completed but not yet persisted.");
124             }
125         } catch (Exception ex) {
126             logger.error("AuthorizationSeedDriver caught an exception: ", ex);
127             throw new RuntimeException(ex);
128         }
129     }
130
131     public void seed() {
132         TransactionStatus status = null;
133         try {
134                 // Push all the authz info into the cspace DB tables -this include default roles, permissions, and permroles
135             store();
136
137             setupSpring();
138             status = beginTransaction("seedData");
139             AuthorizationSeed authzSeed = new AuthorizationSeed();
140             authzSeed.seedPermissions(authzGen.getDefaultPermissions(), authzGen.getDefaultPermissionRoles());
141 //            authzSeed.seedPermissions(exportDir + File.separator + PERMISSION_FILE,
142 //                    exportDir + File.separator + PERMISSION_ROLE_FILE);
143             if (logger.isDebugEnabled()) {
144                 logger.debug("Authorization seeding completed.");
145             }
146         } catch (Exception ex) {
147             if (status != null) {
148                 rollbackTransaction(status);
149             }
150             if (logger.isDebugEnabled()) {
151                 ex.printStackTrace();
152             }
153             throw new RuntimeException(ex);
154         } finally {
155             if (status != null) {
156                 commitTransaction(status);
157             }
158             logout();
159         }
160     }
161
162     private void setupSpring() {
163
164         ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
165                 new String[]{SPRING_SECURITY_METADATA});
166         login();
167         System.setProperty("spring-beans-config", SPRING_SECURITY_METADATA);
168         // authZ local not used but call to AuthZ.get() has side-effect of initializing our Spring Security context
169         AuthZ authZ = AuthZ.get();
170         txManager = (org.springframework.jdbc.datasource.DataSourceTransactionManager) appContext.getBean("transactionManager");
171         if (logger.isDebugEnabled()) {
172             logger.debug("Spring Security setup complete.");
173         }
174     }
175
176     private void login() {
177         //GrantedAuthority cspace_admin = new GrantedAuthorityImpl("ROLE_ADMINISTRATOR");
178         GrantedAuthority spring_security_admin = new GrantedAuthorityImpl("ROLE_SPRING_ADMIN"); //NOTE: Must match with value in applicationContext-authorization-test.xml (aka SPRING_SECURITY_METADATA)
179         HashSet<GrantedAuthority> gauths = new HashSet<GrantedAuthority>();
180         //gauths.add(cspace_admin);
181         gauths.add(spring_security_admin);
182         Authentication authRequest = new UsernamePasswordAuthenticationToken(user, password, gauths);
183         SecurityContextHolder.getContext().setAuthentication(authRequest);
184         if (logger.isDebugEnabled()) {
185             logger.debug("Spring Security login successful for user=" + user);
186         }
187     }
188
189     private void logout() {
190         SecurityContextHolder.getContext().setAuthentication(null);
191         if (logger.isDebugEnabled()) {
192             logger.debug("Spring Security logged out user=" + user);
193         }
194     }
195
196     private void store() throws Exception {
197         EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_AUTHZ_PERSISTENCE_UNIT);
198         EntityManager em = null;
199
200         try {
201             em = emf.createEntityManager();
202             em.getTransaction().begin();
203             
204                 AuthorizationStore authzStore = new AuthorizationStore();
205                 logger.info("Seeding Roles metadata to database.");
206                 for (Role role : authzGen.getDefaultRoles()) {
207                         try {
208                                 authzStore.store(em, role);
209                         } catch (Exception e) {
210                                 //
211                                 // If the role already exists, read it in and replace the instance
212                                 // we're trying to import with the exist one.  This will ensure that the rest
213                                 // of import uses the correct CSID.
214                                 if (e.getCause() instanceof ConstraintViolationException) {
215                                         Role existingRole = authzStore.getRoleByName(role.getRoleName(), role.getTenantId());
216                                         //
217                                         role = existingRole;
218                                 }
219                         }
220                 }
221         
222                 logger.info("Seeding Permissions metadata to database.");
223                 for (Permission perm : authzGen.getDefaultPermissions()) { //FIXME: REM - 3/27/2012 - If we change the CSID of permissions to something like a refname, then we need to check for existing perms just like we did above for roles
224                     authzStore.store(em, perm);
225                 }
226         
227                 logger.info("Seeding Permissions/Roles relationships metadata to database.");
228                 List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
229                 for (PermissionRole pr : authzGen.getDefaultPermissionRoles()) {
230                     PermissionRoleUtil.buildPermissionRoleRel(em, pr, SubjectType.ROLE, permRoleRels, false /*not for delete*/);
231                 }
232                 for (PermissionRoleRel permRoleRel : permRoleRels) {
233                     authzStore.store(em, permRoleRel);
234                 }
235         
236                 em.getTransaction().commit();
237                 em.close();
238                 if (logger.isInfoEnabled()) {
239                     logger.info("All Authorization metadata persisted.");
240                 }
241         } catch (Exception e) {
242             if (em != null && em.getTransaction().isActive()) {
243                 em.getTransaction().rollback();
244             }
245             if (logger.isDebugEnabled()) {
246                 logger.debug("Caught exception and rolling back permission creation: ", e);
247             }
248             throw e;
249         } finally {
250             if (em != null) {
251                 JpaStorageUtils.releaseEntityManagerFactory(emf);
252             }
253         }
254     }
255
256     private TransactionStatus beginTransaction(String name) {
257         DefaultTransactionDefinition def = new DefaultTransactionDefinition();
258         // explicitly setting the transaction name is something that can only be done programmatically
259         def.setName(name);
260         def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
261         return txManager.getTransaction(def);
262     }
263
264     private void rollbackTransaction(TransactionStatus status) {
265         txManager.rollback(status);
266     }
267
268     private void commitTransaction(TransactionStatus status) {
269         txManager.commit(status);
270     }
271 }