]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
f005d12489bca11c51e945ba4f7115e6a3a492b7
[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.jboss.security.SimpleGroup;
49
50 import org.slf4j.Logger;
51 import org.slf4j.LoggerFactory;
52
53 import org.springframework.context.support.ClassPathXmlApplicationContext;
54 import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
55 import org.springframework.security.core.Authentication;
56 import org.springframework.security.core.GrantedAuthority;
57 import org.springframework.security.authentication.jaas.JaasGrantedAuthority;
58 import org.springframework.security.core.context.SecurityContextHolder;
59 import org.springframework.transaction.TransactionDefinition;
60 import org.springframework.transaction.TransactionStatus;
61 import org.springframework.transaction.support.DefaultTransactionDefinition;
62
63 /**
64  * A driver for seeding authorization
65  * @author 
66  */
67 public class AuthorizationSeedDriver {
68
69     final Logger logger = LoggerFactory.getLogger(AuthorizationSeedDriver.class);
70     final static private String SPRING_SECURITY_METADATA = "applicationContext-authorization-test.xml";
71     final static private String ROLE_FILE = "import-roles.xml";
72     final static private String PERMISSION_FILE = "import-permissions.xml";
73     final static private String PERMISSION_ROLE_FILE = "import-permissions-roles.xml";
74     private String user;
75     private String password;
76     private String tenantBindingFile;
77     private String exportDir;
78     private AuthorizationGen authzGen;
79     private org.springframework.jdbc.datasource.DataSourceTransactionManager txManager;
80
81     /**
82      * AuthorizationSeedDriver
83      * @param user to use to establish security context. should be in ROLE_ADMINISTRATOR
84      * @param password
85      * @param tenantBindingFile
86      * @param importDir dir to import permisison/permission role file from. same as
87      * export dir by default
88      * @param exportDir dir to export permission/permission role file to
89      */
90     public AuthorizationSeedDriver(String user, String password,
91             String tenantBindingFile,
92             String exportDir) {
93         if (user == null || user.isEmpty()) {
94             throw new IllegalArgumentException("username required.");
95         }
96         this.user = user;
97
98         if (password == null || password.isEmpty()) {
99             throw new IllegalArgumentException("password required.");
100         }
101         this.password = password;
102         
103         if (tenantBindingFile == null || tenantBindingFile.isEmpty()) {
104             throw new IllegalArgumentException("tenantbinding file are required.");
105         }
106         this.tenantBindingFile = tenantBindingFile;
107         if (exportDir == null || exportDir.isEmpty()) {
108             throw new IllegalArgumentException("exportdir required.");
109         }
110         this.exportDir = exportDir;
111
112     }
113
114     public void generate() {
115         try {
116             authzGen = new AuthorizationGen();
117             authzGen.initialize(tenantBindingFile);
118             authzGen.createDefaultRoles();
119             authzGen.createDefaultPermissions();
120             authzGen.associateDefaultPermissionsRoles();
121             authzGen.exportDefaultRoles(exportDir + File.separator + ROLE_FILE);
122             authzGen.exportDefaultPermissions(exportDir + File.separator + PERMISSION_FILE);
123             authzGen.exportDefaultPermissionRoles(exportDir + File.separator + PERMISSION_ROLE_FILE);
124             if (logger.isDebugEnabled()) {
125                 logger.debug("Authorization generation completed but not yet persisted.");
126             }
127         } catch (Exception ex) {
128             logger.error("AuthorizationSeedDriver caught an exception: ", ex);
129             throw new RuntimeException(ex);
130         }
131     }
132
133     public void seed() {
134         TransactionStatus status = null;
135         try {
136                 // Push all the authz info into the cspace DB tables -this include default roles, permissions, and permroles
137             store();
138
139             setupSpring();
140             status = beginTransaction("seedData");
141             AuthorizationSeed authzSeed = new AuthorizationSeed();
142             authzSeed.seedPermissions(authzGen.getDefaultPermissions(), authzGen.getDefaultPermissionRoles());
143 //            authzSeed.seedPermissions(exportDir + File.separator + PERMISSION_FILE,
144 //                    exportDir + File.separator + PERMISSION_ROLE_FILE);
145             if (logger.isDebugEnabled()) {
146                 logger.debug("Authorization seeding completed.");
147             }
148         } catch (Exception ex) {
149             if (status != null) {
150                 rollbackTransaction(status);
151             }
152             if (logger.isDebugEnabled()) {
153                 ex.printStackTrace();
154             }
155             throw new RuntimeException(ex);
156         } finally {
157             if (status != null) {
158                 commitTransaction(status);
159             }
160             logout();
161         }
162     }
163
164     private void setupSpring() {
165
166         ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext(
167                 new String[]{SPRING_SECURITY_METADATA});
168         login();
169         System.setProperty("spring-beans-config", SPRING_SECURITY_METADATA);
170         // authZ local not used but call to AuthZ.get() has side-effect of initializing our Spring Security context
171         AuthZ authZ = AuthZ.get();
172         txManager = (org.springframework.jdbc.datasource.DataSourceTransactionManager) appContext.getBean("transactionManager");
173         if (logger.isDebugEnabled()) {
174             logger.debug("Spring Security setup complete.");
175         }
176     }
177
178     private void login() {
179         //GrantedAuthority cspace_admin = new JaasGrantedAuthority("ROLE_ADMINISTRATOR", new SimpleGroup("Role"));
180         GrantedAuthority spring_security_admin = new JaasGrantedAuthority("ROLE_SPRING_ADMIN", new SimpleGroup("Role")); //NOTE: Must match with value in applicationContext-authorization-test.xml (aka SPRING_SECURITY_METADATA)
181         HashSet<GrantedAuthority> gauths = new HashSet<GrantedAuthority>();
182         //gauths.add(cspace_admin);
183         gauths.add(spring_security_admin);
184         Authentication authRequest = new UsernamePasswordAuthenticationToken(user, password, gauths);
185         SecurityContextHolder.getContext().setAuthentication(authRequest);
186         if (logger.isDebugEnabled()) {
187             logger.debug("Spring Security login successful for user=" + user);
188         }
189     }
190
191     private void logout() {
192         SecurityContextHolder.getContext().setAuthentication(null);
193         if (logger.isDebugEnabled()) {
194             logger.debug("Spring Security logged out user=" + user);
195         }
196     }
197
198     private void store() throws Exception {
199         EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_AUTHZ_PERSISTENCE_UNIT);
200         EntityManager em = null;
201
202         try {
203             em = emf.createEntityManager();
204             em.getTransaction().begin();
205             
206                 AuthorizationStore authzStore = new AuthorizationStore();
207                 logger.info("Seeding Roles metadata to database.");
208                 for (Role role : authzGen.getDefaultRoles()) {
209                         try {
210                                 authzStore.store(em, role);
211                         } catch (Exception e) {
212                                 //
213                                 // If the role already exists, read it in and replace the instance
214                                 // we're trying to import with the exist one.  This will ensure that the rest
215                                 // of import uses the correct CSID.
216                                 if (e.getCause() instanceof ConstraintViolationException) {
217                                         Role existingRole = authzStore.getRoleByName(role.getRoleName(), role.getTenantId());
218                                         //
219                                         role = existingRole;
220                                 }
221                         }
222                 }
223         
224                 logger.info("Seeding Permissions metadata to database.");
225                 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
226                     authzStore.store(em, perm);
227                 }
228         
229                 logger.info("Seeding Permissions/Roles relationships metadata to database.");
230                 List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
231                 for (PermissionRole pr : authzGen.getDefaultPermissionRoles()) {
232                     PermissionRoleUtil.buildPermissionRoleRel(em, pr, SubjectType.ROLE, permRoleRels, false /*not for delete*/);
233                 }
234                 for (PermissionRoleRel permRoleRel : permRoleRels) {
235                     authzStore.store(em, permRoleRel);
236                 }
237         
238                 em.getTransaction().commit();
239                 em.close();
240                 if (logger.isInfoEnabled()) {
241                     logger.info("All Authorization metadata persisted.");
242                 }
243         } catch (Exception e) {
244             if (em != null && em.getTransaction().isActive()) {
245                 em.getTransaction().rollback();
246             }
247             if (logger.isDebugEnabled()) {
248                 logger.debug("Caught exception and rolling back permission creation: ", e);
249             }
250             throw e;
251         } finally {
252             if (em != null) {
253                 JpaStorageUtils.releaseEntityManagerFactory(emf);
254             }
255         }
256     }
257
258     private TransactionStatus beginTransaction(String name) {
259         DefaultTransactionDefinition def = new DefaultTransactionDefinition();
260         // explicitly setting the transaction name is something that can only be done programmatically
261         def.setName(name);
262         def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
263         return txManager.getTransaction(def);
264     }
265
266     private void rollbackTransaction(TransactionStatus status) {
267         txManager.rollback(status);
268     }
269
270     private void commitTransaction(TransactionStatus status) {
271         txManager.commit(status);
272     }
273 }