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