]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
17f00e974271c25a7aa2600772c8aa3c1a5c4922
[tmp/jakarta-migration.git] /
1 package org.collectionspace.services.common.authorization_mgt;
2
3 import java.sql.Connection;
4 import java.sql.PreparedStatement;
5 import java.sql.ResultSet;
6 import java.sql.SQLException;
7 import java.sql.Statement;
8 import java.util.ArrayList;
9 import java.util.Date;
10 import java.util.HashMap;
11 import java.util.HashSet;
12 import java.util.Hashtable;
13 import java.util.List;
14 import java.util.UUID;
15
16 import javax.naming.NamingException;
17 import javax.persistence.EntityManager;
18 import javax.persistence.EntityManagerFactory;
19
20 import org.collectionspace.authentication.AuthN;
21 import org.collectionspace.services.authorization.AuthZ;
22 import org.collectionspace.services.authorization.CSpaceAction;
23 import org.collectionspace.services.authorization.PermissionException;
24 import org.collectionspace.services.authorization.PermissionRole;
25 import org.collectionspace.services.authorization.PermissionRoleRel;
26 import org.collectionspace.services.authorization.PermissionValue;
27 import org.collectionspace.services.authorization.Role;
28 import org.collectionspace.services.authorization.RoleValue;
29 import org.collectionspace.services.authorization.SubjectType;
30 import org.collectionspace.services.authorization.URIResourceImpl;
31 import org.collectionspace.services.authorization.perms.ActionType;
32 import org.collectionspace.services.authorization.perms.EffectType;
33 import org.collectionspace.services.authorization.perms.Permission;
34 import org.collectionspace.services.authorization.perms.PermissionAction;
35 import org.collectionspace.services.client.Profiler;
36 import org.collectionspace.services.client.RoleClient;
37 import org.collectionspace.services.client.workflow.WorkflowClient;
38 import org.collectionspace.services.common.config.ServiceConfigUtils;
39 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;
40 import org.collectionspace.services.common.context.ServiceBindingUtils;
41 import org.collectionspace.services.common.document.DocumentHandler;
42 import org.collectionspace.services.common.security.SecurityUtils;
43 import org.collectionspace.services.common.storage.DatabaseProductType;
44 import org.collectionspace.services.common.storage.JDBCTools;
45 import org.collectionspace.services.common.storage.jpa.JpaStorageUtils;
46 import org.collectionspace.services.config.service.ServiceBindingType;
47 import org.collectionspace.services.config.tenant.TenantBindingType;
48 import org.collectionspace.services.lifecycle.Lifecycle;
49 import org.collectionspace.services.lifecycle.TransitionDef;
50 import org.collectionspace.services.lifecycle.TransitionDefList;
51
52 //import org.mortbay.log.Log;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.security.acls.model.AlreadyExistsException;
56
57
58 public class AuthorizationCommon {
59         
60         final public static String REFRESH_AUTZ_PROP = "refreshAuthZOnStartup";
61     //
62     // ActionGroup labels/constants
63     //
64         
65         // for READ-WRITE
66     final public static String ACTIONGROUP_CRUDL_NAME = "CRUDL";
67     final public static ActionType[] ACTIONSET_CRUDL = {ActionType.CREATE, ActionType.READ, ActionType.UPDATE, ActionType.DELETE, ActionType.SEARCH};
68     // for READ-ONLY
69     final public static String ACTIONGROUP_RL_NAME = "RL";
70     final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};
71         
72         static ActionGroup ACTIONGROUP_CRUDL;
73         static ActionGroup ACTIONGROUP_RL;
74         
75         // A static block to initialize the predefined action groups
76         static {
77                 // For admin
78                 ACTIONGROUP_CRUDL = new ActionGroup();
79                 ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;
80                 ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;
81                 // For reader
82                 ACTIONGROUP_RL = new ActionGroup();
83                 ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;
84                 ACTIONGROUP_RL.actions = ACTIONSET_RL;
85
86         }
87         
88     final static Logger logger = LoggerFactory.getLogger(AuthorizationCommon.class);
89
90     final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";
91     final public static String ROLE_TENANT_READER = "TENANT_READER";
92         
93     public static final String TENANT_MANAGER_USER = "tenantManager"; 
94     public static final String TENANT_MANAGER_SCREEN_NAME = TENANT_MANAGER_USER; 
95     public static final String DEFAULT_TENANT_MANAGER_PASSWORD = "manage"; 
96     public static final String DEFAULT_TENANT_MANAGER_EMAIL = "tenantManager@collectionspace.org"; 
97     
98     public static final String TENANT_ADMIN_ACCT_PREFIX = "admin@"; 
99     public static final String TENANT_READER_ACCT_PREFIX = "reader@"; 
100     public static final String ROLE_PREFIX = "ROLE_"; 
101     public static final String TENANT_ADMIN_ROLE_SUFFIX = "_TENANT_ADMINISTRATOR"; 
102     public static final String TENANT_READER_ROLE_SUFFIX = "_TENANT_READER"; 
103     public static final String DEFAULT_ADMIN_PASSWORD = "Administrator";
104     public static final String DEFAULT_READER_PASSWORD = "reader";
105     
106     // SQL for init tasks
107         final private static String INSERT_ACCOUNT_ROLE_SQL_MYSQL = 
108                         "INSERT INTO accounts_roles(account_id, user_id, role_id, role_name, created_at)"
109                                         +" VALUES(?, ?, ?, ?, now())";
110         final private static String INSERT_ACCOUNT_ROLE_SQL_POSTGRES =
111                         "INSERT INTO accounts_roles(HJID, account_id, user_id, role_id, role_name, created_at)"
112                                         +" VALUES(nextval('hibernate_sequence'), ?, ?, ?, ?, now())";
113         final private static String QUERY_USERS_SQL = 
114                 "SELECT username FROM users WHERE username LIKE '"
115                         +TENANT_ADMIN_ACCT_PREFIX+"%' OR username LIKE '"+TENANT_READER_ACCT_PREFIX+"%'";
116         final private static String INSERT_USER_SQL = 
117                         "INSERT INTO users (username,passwd, created_at) VALUES (?,?, now())";
118         final private static String INSERT_ACCOUNT_SQL = 
119                         "INSERT INTO accounts_common "
120                                         + "(csid, email, userid, status, screen_name, metadata_protection, roles_protection, created_at) "
121                                         + "VALUES (?,?,?,'ACTIVE',?, 'immutable', 'immutable', now())";
122         
123         // TENANT MANAGER specific SQL
124         final private static String QUERY_TENANT_MGR_USER_SQL = 
125                 "SELECT username FROM users WHERE username = '"+TENANT_MANAGER_USER+"'";
126         final private static String GET_TENANT_MGR_ROLE_SQL =
127                         "SELECT csid from roles WHERE tenant_id='" + AuthN.ALL_TENANTS_MANAGER_TENANT_ID + "' and rolename=?";
128
129     public static Role getRole(String tenantId, String displayName) {
130         Role role = null;
131         
132         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
133         role = AuthorizationStore.getRoleByName(roleName, tenantId);
134         
135         return role;
136     }
137     
138     public static Role getRole(EntityManager em, String tenantId, String displayName) {
139         Role role = null;
140         
141         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);
142         role = AuthorizationStore.getRoleByName(em, roleName, tenantId);
143         
144         return role;
145     }
146     
147     
148     public static Role createRole(String tenantId, String name, String description) {
149         return createRole(tenantId, name, description, false /* mutable by default */);
150     }
151     
152     public static Role createRole(String tenantId, String name, String description, boolean immutable) {
153         Role role = new Role();
154         
155         role.setCreatedAtItem(new Date());
156         role.setDisplayName(name);
157         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, name);     
158         role.setRoleName(roleName);
159         String id = UUID.randomUUID().toString(); //FIXME: The qualified role name should be unique enough to use as an ID/key
160         role.setCsid(id);
161                 role.setDescription(description);
162         role.setTenantId(tenantId);
163         if (immutable == true) {
164                 role.setMetadataProtection(RoleClient.IMMUTABLE);
165                 role.setPermsProtection(RoleClient.IMMUTABLE);
166         }
167         
168         return role;
169     }
170     
171     /**
172      * Add permission to the Spring Security tables
173      * with assumption that resource is of type URI
174      * @param permission configuration
175      */
176     public static void addPermissionsForUri(Permission perm,
177             PermissionRole permRole) throws PermissionException {
178         //
179         // First check the integrity of the incoming arguments.
180         //
181         if (!perm.getCsid().equals(permRole.getPermission().get(0).getPermissionId())) {
182             throw new IllegalArgumentException("permission ids do not"
183                     + " match for role=" + permRole.getRole().get(0).getRoleName()
184                     + " with permissionId=" + permRole.getPermission().get(0).getPermissionId()
185                     + " for permission with csid=" + perm.getCsid());
186         }
187         
188         List<String> principals = new ArrayList<String>();        
189         for (RoleValue roleValue : permRole.getRole()) {
190             principals.add(roleValue.getRoleName());
191         }
192         List<PermissionAction> permActions = perm.getAction();
193         for (PermissionAction permAction : permActions) {
194                 try {
195                     CSpaceAction action = URIResourceImpl.getAction(permAction.getName()); 
196                     URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
197                             perm.getResourceName(), action);
198                     boolean grant = perm.getEffect().equals(EffectType.PERMIT) ? true : false;
199                     AuthZ.get().addPermissions(uriRes, principals.toArray(new String[0]), grant);//CSPACE-4967
200                 } catch (PermissionException e) {
201                         //
202                         // Only throw the exception if it is *not* an already-exists exception
203                         //
204                         if (e.getCause() instanceof AlreadyExistsException == false) {
205                                 throw e;
206                         }
207                 }
208         }
209     }
210     
211     private static Connection getConnection(String databaseName) throws NamingException, SQLException {
212         return JDBCTools.getConnection(JDBCTools.CSPACE_DATASOURCE_NAME,
213                         databaseName);
214     }
215     
216     /*
217      * Spring security seems to require that all of our role names start
218      * with the ROLE_PREFIX string.
219      */
220     public static String getQualifiedRoleName(String tenantId, String name) {
221         String result = name;
222         
223         String qualifiedName = ROLE_PREFIX + tenantId.toUpperCase() + "_" + name.toUpperCase();         
224         if (name.equals(qualifiedName) == false) {
225                 result = qualifiedName;
226         }
227         
228         return result;
229     }
230         
231     private static ActionGroup getActionGroup(String actionGroupStr) {
232         ActionGroup result = null;
233         
234         if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_CRUDL_NAME)) {
235                 result = ACTIONGROUP_CRUDL;
236         } else if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_RL_NAME)) {
237                 result = ACTIONGROUP_RL;
238         }
239         
240         return result;
241     }
242     
243     public static Permission createPermission(String tenantId,
244                 String resourceName,
245                 String description,
246                 String actionGroupStr) {
247         Permission result = null;
248         
249         ActionGroup actionGroup = getActionGroup(actionGroupStr);
250         result = createPermission(tenantId, resourceName, description, actionGroup);
251         
252         return result;
253     }
254     
255     private static Permission createPermission(String tenantId,
256                 String resourceName,
257                 String description,
258                 ActionGroup actionGroup) {
259         String id = tenantId
260                         + "-" + resourceName.replace('/', '_') // Remove the slashes so the ID can be used in a URI/URL
261                         + "-" + actionGroup.name;
262         Permission perm = new Permission();
263         perm.setCsid(id);
264         perm.setDescription(description);
265         perm.setCreatedAtItem(new Date());
266         perm.setResourceName(resourceName.toLowerCase().trim());
267         perm.setEffect(EffectType.PERMIT);
268         perm.setTenantId(tenantId);
269         
270         perm.setActionGroup(actionGroup.name);
271         ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();
272         perm.setAction(pas);
273         for (ActionType actionType : actionGroup.actions) {
274                 PermissionAction permAction = createPermissionAction(perm, actionType);
275                 pas.add(permAction);
276         }
277         
278         return perm;
279     }
280     
281     private static Permission createWorkflowPermission(TenantBindingType tenantBinding,
282                 ServiceBindingType serviceBinding,
283                 String transitionVerb,
284                 ActionGroup actionGroup)
285     {
286         Permission result = null;
287         String workFlowServiceSuffix;
288         String transitionName;
289         if (transitionVerb != null) {
290                 transitionName = transitionVerb;
291                 workFlowServiceSuffix = WorkflowClient.SERVICE_AUTHZ_SUFFIX;
292         } else {
293                 transitionName = ""; //since the transitionDef was null, we're assuming that this is the base workflow permission to be created                 
294                 workFlowServiceSuffix = WorkflowClient.SERVICE_PATH;
295         }
296         
297         String tenantId = tenantBinding.getId();
298         String resourceName = "/"
299                         + serviceBinding.getName().toLowerCase().trim()
300                         + workFlowServiceSuffix
301                         + transitionName;
302         String description = "A generated workflow permission for actiongroup " + actionGroup.name;
303         result = createPermission(tenantId, resourceName, description, actionGroup);
304         
305         if (logger.isDebugEnabled() == true) {
306                 logger.debug("Generated a workflow permission: "
307                                 + result.getResourceName()
308                                 + ":" + transitionName
309                                 + ":" + "tenant id=" + result.getTenantId()
310                                 + ":" + actionGroup.name);
311         }
312         
313         return result;
314     }
315     
316     private static PermissionRole createPermissionRole(EntityManager em,
317                 Permission permission,
318                 Role role,
319                 boolean enforceTenancy) throws Exception
320     {
321         PermissionRole permRole = new PermissionRole();
322         // Check to see if the tenant ID of the permission and the tenant ID of the role match
323         boolean tenantIdsMatch = role.getTenantId().equalsIgnoreCase(permission.getTenantId());
324         if (tenantIdsMatch == false && enforceTenancy == false) {
325                 tenantIdsMatch = true; // If we don't need to enforce tenancy then we'll just consider them matched.
326         }
327                         
328                 if (tenantIdsMatch == true) {
329                 permRole.setSubject(SubjectType.ROLE);
330                 //
331                 // Set of the permission value list of the permrole
332                 //
333                 List<PermissionValue> permValues = new ArrayList<PermissionValue>();
334                 PermissionValue permValue = new PermissionValue();
335                 permValue.setPermissionId(permission.getCsid());
336                 permValue.setResourceName(permission.getResourceName().toLowerCase());
337                 permValue.setActionGroup(permission.getActionGroup());
338                 permValues.add(permValue);
339                 permRole.setPermission(permValues);
340                 //
341                 // Set of the role value list of the permrole
342                 //
343                 List<RoleValue> roleValues = new ArrayList<RoleValue>();
344                 RoleValue rv = new RoleValue();
345             // This needs to use the qualified name, not the display name
346             rv.setRoleName(role.getRoleName());
347             rv.setRoleId(role.getCsid());
348             roleValues.add(rv);
349             permRole.setRole(roleValues);
350                 } else {
351                 String errMsg = "The tenant ID of the role: " + role.getTenantId()
352                                 + " did not match the tenant ID of the permission: " + permission.getTenantId();
353                 throw new Exception(errMsg);
354                 }
355         
356         return permRole;
357     }
358     
359     private static Hashtable<String, String> getTenantNamesFromConfig(TenantBindingConfigReaderImpl tenantBindingConfigReader) {
360
361         // Note that this only handles tenants not marked as "createDisabled"
362         Hashtable<String, TenantBindingType> tenantBindings =
363                         tenantBindingConfigReader.getTenantBindings();
364         Hashtable<String, String> tenantInfo = new Hashtable<String, String>();
365         for (TenantBindingType tenantBinding : tenantBindings.values()) {
366                 String tId = tenantBinding.getId();
367                 String tName = tenantBinding.getName();
368                 tenantInfo.put(tId, tName);
369                 if (logger.isDebugEnabled()) {
370                         logger.debug("getTenantNamesFromConfig found configured tenant id: "+tId+" name: "+tName);
371                 }
372         }
373         return tenantInfo;
374     }
375     
376     private static ArrayList<String> compileExistingTenants(Connection conn, Hashtable<String, String> tenantInfo)
377         throws SQLException, Exception {
378         Statement stmt = null;
379         ArrayList<String> existingTenants = new ArrayList<String>();
380         // First find or create the tenants
381         final String queryTenantSQL = "SELECT id,name FROM tenants";
382         try {
383                 stmt = conn.createStatement();
384                 ResultSet rs = stmt.executeQuery(queryTenantSQL);
385                 while (rs.next()) {
386                         String tId = rs.getString("id");
387                         String tName = rs.getString("name");
388                         if(tenantInfo.containsKey(tId)) {
389                                 existingTenants.add(tId);
390                                 if(!tenantInfo.get(tId).equalsIgnoreCase(tName)) {
391                                         logger.warn("Configured name for tenant: "
392                                                         +tId+" in repository: "+tName
393                                                         +" does not match config'd name: "+ tenantInfo.get(tId));
394                                 }
395                         }
396                 }
397                 rs.close();
398         } catch(Exception e) {
399                 throw e;
400         } finally {
401                 if(stmt!=null)
402                         stmt.close();
403         }
404
405         return existingTenants;
406     }
407     
408     private static void createMissingTenants(Connection conn, Hashtable<String, String> tenantInfo,
409                 ArrayList<String> existingTenants) throws SQLException, Exception {
410                 // Need to define and look for a createDisabled attribute in tenant config
411         final String insertTenantSQL = 
412                 "INSERT INTO tenants (id,name,disabled,created_at) VALUES (?,?,FALSE,now())";
413         PreparedStatement pstmt = null;
414         try {
415                 pstmt = conn.prepareStatement(insertTenantSQL); // create a statement
416                 for(String tId : tenantInfo.keySet()) {
417                         if(existingTenants.contains(tId)) {
418                                 if (logger.isDebugEnabled()) {
419                                         logger.debug("createMissingTenants: tenant exists (skipping): "
420                                                         +tenantInfo.get(tId));
421                                 }
422                                 continue;
423                         }
424                         pstmt.setString(1, tId);                                        // set id param
425                         pstmt.setString(2, tenantInfo.get(tId));        // set name param
426                         if (logger.isDebugEnabled()) {
427                                 logger.debug("createMissingTenants adding entry for tenant: "+tId);
428                         }
429                         pstmt.executeUpdate();
430                 }
431                 pstmt.close();
432         } catch(Exception e) {
433                 throw e;
434         } finally {
435                 if(pstmt!=null)
436                         pstmt.close();
437         }
438     }
439     
440     private static ArrayList<String> findOrCreateDefaultUsers(Connection conn, Hashtable<String, String> tenantInfo) 
441                 throws SQLException, Exception {
442         // Second find or create the users
443         Statement stmt = null;
444         PreparedStatement pstmt = null;
445         ArrayList<String> usersInRepo = new ArrayList<String>();
446         try {
447                 stmt = conn.createStatement();
448                 ResultSet rs = stmt.executeQuery(QUERY_USERS_SQL);
449                 while (rs.next()) {
450                         String uName = rs.getString("username");
451                         usersInRepo.add(uName);
452                 }
453                 rs.close();
454                 pstmt = conn.prepareStatement(INSERT_USER_SQL); // create a statement
455                 for(String tName : tenantInfo.values()) {
456                         String adminAcctName = getDefaultAdminUserID(tName);
457                         if(!usersInRepo.contains(adminAcctName)) {
458                                 String secEncPasswd = SecurityUtils.createPasswordHash(
459                                                 adminAcctName, DEFAULT_ADMIN_PASSWORD);
460                                 pstmt.setString(1, adminAcctName);      // set username param
461                                 pstmt.setString(2, secEncPasswd);       // set passwd param
462                                 if (logger.isDebugEnabled()) {
463                                         logger.debug("createDefaultUsersAndAccounts adding user: "
464                                                         +adminAcctName+" for tenant: "+tName);
465                                 }
466                                 pstmt.executeUpdate();
467                         } else if (logger.isDebugEnabled()) {
468                                 logger.debug("createDefaultUsersAndAccounts: user: "+adminAcctName
469                                                 +" already exists - skipping.");
470                         }
471
472
473                         String readerAcctName =  getDefaultReaderUserID(tName);
474                         if(!usersInRepo.contains(readerAcctName)) {
475                                 String secEncPasswd = SecurityUtils.createPasswordHash(
476                                                 readerAcctName, DEFAULT_READER_PASSWORD);
477                                 pstmt.setString(1, readerAcctName);     // set username param
478                                 pstmt.setString(2, secEncPasswd);       // set passwd param
479                                 if (logger.isDebugEnabled()) {
480                                         logger.debug("createDefaultUsersAndAccounts adding user: "
481                                                         +readerAcctName+" for tenant: "+tName);
482                                 }
483                                 pstmt.executeUpdate();
484                         } else if (logger.isDebugEnabled()) {
485                                 logger.debug("createDefaultUsersAndAccounts: user: "+readerAcctName
486                                                 +" already exists - skipping.");
487                         }
488                 }
489                 pstmt.close();
490         } catch(Exception e) {
491                 throw e;
492         } finally {
493                 if(stmt!=null)
494                         stmt.close();
495                 if(pstmt!=null)
496                         pstmt.close();
497         }
498         return usersInRepo;
499     }
500     
501     private static void findOrCreateDefaultAccounts(Connection conn, Hashtable<String, String> tenantInfo,
502                 ArrayList<String> usersInRepo,
503                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
504                         throws SQLException, Exception {
505         // Third, create the accounts. Assume that if the users were already there,
506         // then the accounts were as well
507         PreparedStatement pstmt = null;
508         try {
509                 pstmt = conn.prepareStatement(INSERT_ACCOUNT_SQL); // create a statement
510                 for(String tId : tenantInfo.keySet()) {
511                         String tName = tenantInfo.get(tId);
512                         String adminCSID = UUID.randomUUID().toString();
513                         tenantAdminAcctCSIDs.put(tId, adminCSID);
514                         String adminAcctName =  getDefaultAdminUserID(tName);
515                         if(!usersInRepo.contains(adminAcctName)) {
516                                 pstmt.setString(1, adminCSID);                  // set csid param
517                                 pstmt.setString(2, adminAcctName);      // set email param (bogus)
518                                 pstmt.setString(3, adminAcctName);      // set userid param
519                                 pstmt.setString(4, "Administrator");// set screen name param
520                                 if (logger.isDebugEnabled()) {
521                                         logger.debug("createDefaultAccounts adding account: "
522                                                         +adminAcctName+" for tenant: "+tName);
523                                 }
524                                 pstmt.executeUpdate();
525                         } else if (logger.isDebugEnabled()) {
526                                 logger.debug("createDefaultAccounts: user: "+adminAcctName
527                                                 +" already exists - skipping account generation.");
528                         }
529
530                         String readerCSID = UUID.randomUUID().toString();       
531                         tenantReaderAcctCSIDs.put(tId, readerCSID);
532                         String readerAcctName =  getDefaultReaderUserID(tName);
533                         if(!usersInRepo.contains(readerAcctName)) {
534                                 pstmt.setString(1, readerCSID);         // set csid param
535                                 pstmt.setString(2, readerAcctName);     // set email param (bogus)
536                                 pstmt.setString(3, readerAcctName);     // set userid param
537                                 pstmt.setString(4, "Reader");           // set screen name param
538                                 if (logger.isDebugEnabled()) {
539                                         logger.debug("createDefaultAccounts adding account: "
540                                                         +readerAcctName+" for tenant: "+tName);
541                                 }
542                                 pstmt.executeUpdate();
543                         } else if (logger.isDebugEnabled()) {
544                                 logger.debug("createDefaultAccounts: user: "+readerAcctName
545                                                 +" already exists - skipping account creation.");
546                         }
547                 }
548                 pstmt.close();
549         } catch(Exception e) {
550                 throw e;
551         } finally {
552                 if(pstmt!=null)
553                         pstmt.close();
554         }
555     }
556     
557     private static boolean findOrCreateTenantManagerUserAndAccount(Connection conn) 
558                         throws SQLException, Exception {
559         // Find or create the special tenant manager account.
560         // Later can make the user name for tenant manager be configurable, settable.
561         Statement stmt = null;
562         PreparedStatement pstmt = null;
563         boolean created = false;
564         try {
565                 boolean foundTMgrUser = false;
566                 stmt = conn.createStatement();
567                 ResultSet rs = stmt.executeQuery(QUERY_TENANT_MGR_USER_SQL);
568                 // Should only find one - only consider it
569                 if(rs.next()) {
570                         String uName = rs.getString("username");
571                         foundTMgrUser = uName.equals(TENANT_MANAGER_USER);
572                 }
573                 rs.close();
574                 if(!foundTMgrUser) {
575                         pstmt = conn.prepareStatement(INSERT_USER_SQL); // create a statement
576                         String secEncPasswd = SecurityUtils.createPasswordHash(
577                                         TENANT_MANAGER_USER, DEFAULT_TENANT_MANAGER_PASSWORD);
578                         pstmt.setString(1, TENANT_MANAGER_USER);        // set username param
579                         pstmt.setString(2, secEncPasswd);       // set passwd param
580                         if (logger.isDebugEnabled()) {
581                                 logger.debug("findOrCreateTenantManagerUserAndAccount adding tenant manager user: "
582                                                 +TENANT_MANAGER_USER);
583                         }
584                         pstmt.executeUpdate();
585                 pstmt.close();
586                 // Now create the account to match
587                         pstmt = conn.prepareStatement(INSERT_ACCOUNT_SQL); // create a statement
588                                 pstmt.setString(1, AuthN.TENANT_MANAGER_ACCT_ID);                // set csid param
589                                 pstmt.setString(2, DEFAULT_TENANT_MANAGER_EMAIL);       // set email param (bogus)
590                                 pstmt.setString(3, TENANT_MANAGER_USER);        // set userid param
591                                 pstmt.setString(4, TENANT_MANAGER_SCREEN_NAME);// set screen name param
592                                 if (logger.isDebugEnabled()) {
593                                         logger.debug("findOrCreateTenantManagerUserAndAccount adding tenant manager account: "
594                                                         +TENANT_MANAGER_USER);
595                                 }
596                                 pstmt.executeUpdate();
597                         pstmt.close();
598                         created = true;
599                 } else if (logger.isDebugEnabled()) {
600                         logger.debug("findOrCreateTenantManagerUserAndAccount: tenant manager: "+TENANT_MANAGER_USER
601                                         +" already exists.");
602                 }
603         } catch(Exception e) {
604                 throw e;
605         } finally {
606                 if(stmt!=null)
607                         stmt.close();
608                 if(pstmt!=null)
609                         pstmt.close();
610         }
611         return created;
612     }
613     
614     private static void bindDefaultAccountsToTenants(Connection conn, DatabaseProductType databaseProductType,
615                 Hashtable<String, String> tenantInfo, ArrayList<String> usersInRepo,
616                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
617                         throws SQLException, Exception {
618         // Fourth, bind accounts to tenants. Assume that if the users were already there,
619         // then the accounts were bound to tenants correctly
620         PreparedStatement pstmt = null;
621         try {
622                 String insertAccountTenantSQL;
623                 if (databaseProductType == DatabaseProductType.MYSQL) {
624                         insertAccountTenantSQL =
625                                         "INSERT INTO accounts_tenants (TENANTS_ACCOUNTS_COMMON_CSID,tenant_id) "
626                                                         + " VALUES(?, ?)";
627                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
628                         insertAccountTenantSQL =
629                                         "INSERT INTO accounts_tenants (HJID, TENANTS_ACCOUNTS_COMMON_CSID,tenant_id) "
630                                                         + " VALUES(nextval('hibernate_sequence'), ?, ?)";
631                 } else {
632                         throw new Exception("Unrecognized database system.");
633                 }
634                 pstmt = conn.prepareStatement(insertAccountTenantSQL); // create a statement
635                 for(String tId : tenantInfo.keySet()) {
636                         String tName = tenantInfo.get(tId);
637                         if(!usersInRepo.contains(getDefaultAdminUserID(tName))) {
638                                 String adminAcct = tenantAdminAcctCSIDs.get(tId);
639                                 pstmt.setString(1, adminAcct);          // set acct CSID param
640                                 pstmt.setString(2, tId);                        // set tenant_id param
641                                 if (logger.isDebugEnabled()) {
642                                         logger.debug("createDefaultAccounts binding account id: "
643                                                         +adminAcct+" to tenant id: "+tId);
644                                 }
645                                 pstmt.executeUpdate();
646                         }
647                         if(!usersInRepo.contains(getDefaultReaderUserID(tName))) {
648                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);
649                                 pstmt.setString(1, readerAcct);         // set acct CSID param
650                                 pstmt.setString(2, tId);                        // set tenant_id param
651                                 if (logger.isDebugEnabled()) {
652                                         logger.debug("createDefaultAccounts binding account id: "
653                                                         +readerAcct+" to tenant id: "+tId);
654                                 }
655                                 pstmt.executeUpdate();
656                         }
657                 }
658                 pstmt.close();
659         } catch(Exception e) {
660                 throw e;
661         } finally {
662                 if(pstmt!=null)
663                         pstmt.close();
664         }
665     }
666     
667     
668     private static String findOrCreateDefaultRoles(Connection conn, Hashtable<String, String> tenantInfo,
669                 Hashtable<String, String> tenantAdminRoleCSIDs, Hashtable<String, String> tenantReaderRoleCSIDs) 
670                         throws SQLException, Exception {
671         // Fifth, fetch and save the default roles
672                 String springAdminRoleCSID = null;
673         Statement stmt = null;
674         PreparedStatement pstmt = null;
675         try {
676                 final String querySpringRole = 
677                                 "SELECT csid from roles WHERE rolename='"+AuthN.ROLE_SPRING_ADMIN_NAME+"'";
678                 stmt = conn.createStatement();
679                 ResultSet rs = stmt.executeQuery(querySpringRole);
680                 if(rs.next()) {
681                         springAdminRoleCSID = rs.getString(1);
682                         if (logger.isDebugEnabled()) {
683                                 logger.debug("createDefaultAccounts found Spring Admin role: "
684                                                 +springAdminRoleCSID);
685                         }
686                 } else {
687                         final String insertSpringAdminRoleSQL =
688                                         "INSERT INTO roles (csid, rolename, displayName, rolegroup, created_at, tenant_id) "
689                                                         + "VALUES ('-1', 'ROLE_SPRING_ADMIN', 'SPRING_ADMIN', 'Spring Security Administrator', now(), '0')";
690                         stmt.executeUpdate(insertSpringAdminRoleSQL);
691                         springAdminRoleCSID = "-1";
692                         if (logger.isDebugEnabled()) {
693                                 logger.debug("createDefaultAccounts CREATED Spring Admin role: "
694                                                 +springAdminRoleCSID);
695                         }
696                 }
697                 rs.close();
698                 final String getRoleCSIDSql =
699                                 "SELECT csid from roles WHERE tenant_id=? and rolename=?";
700                 pstmt = conn.prepareStatement(getRoleCSIDSql); // create a statement
701                 rs = null;
702                 for(String tId : tenantInfo.keySet()) {
703                         pstmt.setString(1, tId);                                                // set tenant_id param
704                         pstmt.setString(2, getDefaultAdminRole(tId));   // set rolename param
705                         rs = pstmt.executeQuery();
706                         // extract data from the ResultSet
707                         if(!rs.next()) {
708                                 throw new RuntimeException("Cannot find role: "+getDefaultAdminRole(tId)
709                                                 +" for tenant id: "+tId+" in roles!");
710                         }
711                         String tenantAdminRoleCSID = rs.getString(1);
712                         if (logger.isDebugEnabled()) {
713                                 logger.debug("createDefaultAccounts found role: "
714                                                 +getDefaultAdminRole(tId)+"("+tenantAdminRoleCSID
715                                                 +") for tenant id: "+tId);
716                         }
717                         tenantAdminRoleCSIDs.put(tId, tenantAdminRoleCSID);
718                         pstmt.setString(1, tId);                                                // set tenant_id param
719                         pstmt.setString(2, getDefaultReaderRole(tId));  // set rolename param
720                         rs.close();
721                         rs = pstmt.executeQuery();
722                         // extract data from the ResultSet
723                         if(!rs.next()) {
724                                 throw new RuntimeException("Cannot find role: "+getDefaultReaderRole(tId)
725                                                 +" for tenant id: "+tId+" in roles!");
726                         }
727                         String tenantReaderRoleCSID = rs.getString(1);
728                         if (logger.isDebugEnabled()) {
729                                 logger.debug("createDefaultAccounts found role: "
730                                                 +getDefaultReaderRole(tId)+"("+tenantReaderRoleCSID
731                                                 +") for tenant id: "+tId);
732                         }
733                         tenantReaderRoleCSIDs.put(tId, tenantReaderRoleCSID);
734                         rs.close();
735                 }
736                 pstmt.close();
737         } catch(Exception e) {
738                 throw e;
739         } finally {
740                 if(stmt!=null)
741                         stmt.close();
742                 if(pstmt!=null)
743                         pstmt.close();
744         }
745         return springAdminRoleCSID;
746     }
747
748     private static String findTenantManagerRole(Connection conn ) 
749                         throws SQLException, RuntimeException, Exception {
750                 String tenantMgrRoleCSID = null;
751         PreparedStatement pstmt = null;
752         try {
753                 String rolename = getQualifiedRoleName(AuthN.ALL_TENANTS_MANAGER_TENANT_ID, 
754                                 AuthN.ROLE_ALL_TENANTS_MANAGER);                
755                 pstmt = conn.prepareStatement(GET_TENANT_MGR_ROLE_SQL); // create a statement
756                 ResultSet rs = null;
757                 pstmt.setString(1, rolename);   // set rolename param
758                 rs = pstmt.executeQuery();
759                 if(rs.next()) {
760                         tenantMgrRoleCSID = rs.getString(1);
761                         if (logger.isDebugEnabled()) {
762                                 logger.debug("findTenantManagerRole found Tenant Mgr role: "
763                                                 +tenantMgrRoleCSID);
764                         }
765                 }
766                 rs.close();
767         } catch(Exception e) {
768                 throw e;
769         } finally {
770                 if(pstmt!=null)
771                         pstmt.close();
772         }
773         if(tenantMgrRoleCSID==null)
774                 throw new RuntimeException("findTenantManagerRole: Cound not find tenant Manager Role!");
775         return tenantMgrRoleCSID;
776     }
777
778     private static void bindAccountsToRoles(Connection conn,  DatabaseProductType databaseProductType,
779                 Hashtable<String, String> tenantInfo, ArrayList<String> usersInRepo,
780                 String springAdminRoleCSID,
781                 Hashtable<String, String> tenantAdminRoleCSIDs, Hashtable<String, String> tenantReaderRoleCSIDs,
782                 Hashtable<String, String> tenantAdminAcctCSIDs, Hashtable<String, String> tenantReaderAcctCSIDs) 
783                         throws SQLException, Exception {
784         // Sixth, bind the accounts to roles. If the users already existed,
785         // we'll assume they were set up correctly.
786         PreparedStatement pstmt = null;
787         try {
788                 String insertAccountRoleSQL;
789                 if (databaseProductType == DatabaseProductType.MYSQL) {
790                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_MYSQL;
791                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
792                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_POSTGRES;
793                 } else {
794                         throw new Exception("Unrecognized database system.");
795                 }
796                 if (logger.isDebugEnabled()) {
797                         logger.debug("createDefaultAccounts binding accounts to roles with SQL:\n"
798                                         +insertAccountRoleSQL);
799                 }
800                 pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement
801                 for(String tId : tenantInfo.keySet()) {
802                         String adminUserId =  getDefaultAdminUserID(tenantInfo.get(tId));
803                         if(!usersInRepo.contains(adminUserId)) {
804                                 String adminAcct = tenantAdminAcctCSIDs.get(tId);
805                                 String adminRoleId = tenantAdminRoleCSIDs.get(tId);
806                                 pstmt.setString(1, adminAcct);          // set acct CSID param
807                                 pstmt.setString(2, adminUserId);        // set user_id param
808                                 pstmt.setString(3, adminRoleId);        // set role_id param
809                                 pstmt.setString(4, getDefaultAdminRole(tId));   // set rolename param
810                                 if (logger.isDebugEnabled()) {
811                                         logger.debug("createDefaultAccounts binding account: "
812                                                         +adminUserId+" to Admin role("+adminRoleId
813                                                         +") for tenant id: "+tId);
814                                 }
815                                 pstmt.executeUpdate();
816                                 // Now add the Spring Admin Role to the admin accounts
817                                 pstmt.setString(3, springAdminRoleCSID);        // set role_id param
818                                 pstmt.setString(4, AuthN.ROLE_SPRING_ADMIN_NAME);               // set rolename param
819                                 if (logger.isDebugEnabled()) {
820                                         logger.debug("createDefaultAccounts binding account: "
821                                                         +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);
822                                 }
823                                 pstmt.executeUpdate();
824                         }
825                         String readerUserId = getDefaultReaderUserID(tenantInfo.get(tId));
826                         if(!usersInRepo.contains(readerUserId)) {
827                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);
828                                 String readerRoleId = tenantReaderRoleCSIDs.get(tId);
829                                 pstmt.setString(1, readerAcct);         // set acct CSID param
830                                 pstmt.setString(2, readerUserId);       // set user_id param
831                                 pstmt.setString(3, readerRoleId);       // set role_id param
832                                 pstmt.setString(4, getDefaultReaderRole(tId));  // set rolename param
833                                 if (logger.isDebugEnabled()) {
834                                         logger.debug("createDefaultAccounts binding account: "
835                                                         +readerUserId+" to Reader role("+readerRoleId
836                                                         +") for tenant id: "+tId);
837                                 }
838                                 pstmt.executeUpdate();
839                         }
840                 }
841                 pstmt.close();
842         } catch(Exception e) {
843                 throw e;
844         } finally {
845                 if(pstmt!=null)
846                         pstmt.close();
847         }
848     }
849     
850     private static void bindTenantManagerAccountRole(Connection conn,  DatabaseProductType databaseProductType,
851                 String tenantManagerUserID, String tenantManagerAccountID, String tenantManagerRoleID, String tenantManagerRoleName ) 
852                         throws SQLException, Exception {
853         PreparedStatement pstmt = null;
854         try {
855                 String insertAccountRoleSQL;
856                 if (databaseProductType == DatabaseProductType.MYSQL) {
857                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_MYSQL;
858                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {
859                         insertAccountRoleSQL = INSERT_ACCOUNT_ROLE_SQL_POSTGRES;
860                 } else {
861                         throw new Exception("Unrecognized database system.");
862                 }
863                 if (logger.isDebugEnabled()) {
864                         logger.debug("bindTenantManagerAccountRole binding account to role with SQL:\n"
865                                         +insertAccountRoleSQL);
866                 }
867                 pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement
868                 pstmt.setString(1, tenantManagerAccountID);             // set acct CSID param
869                 pstmt.setString(2, tenantManagerUserID);        // set user_id param
870                 pstmt.setString(3, tenantManagerRoleID);        // set role_id param
871                 pstmt.setString(4, tenantManagerRoleName);      // set rolename param
872                 if (logger.isDebugEnabled()) {
873                         logger.debug("bindTenantManagerAccountRole binding user: "
874                                         +tenantManagerUserID+" to Admin role("+tenantManagerRoleName+")");
875                 }
876                 pstmt.executeUpdate();
877                 /* At this point, tenant manager should not need the Spring Admin Role
878                 pstmt.setString(3, springAdminRoleCSID);        // set role_id param
879                 pstmt.setString(4, SPRING_ADMIN_ROLE);          // set rolename param
880                 if (logger.isDebugEnabled()) {
881                         logger.debug("createDefaultAccounts binding account: "
882                                         +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);
883                 }
884                 pstmt.executeUpdate();
885                 */
886                 pstmt.close();
887         } catch(Exception e) {
888                 throw e;
889         } finally {
890                 if(pstmt!=null)
891                         pstmt.close();
892         }
893     }
894     
895     public static void createDefaultAccounts(
896                 TenantBindingConfigReaderImpl tenantBindingConfigReader,
897                 DatabaseProductType databaseProductType,
898                 String cspaceDatabaseName) throws Exception {
899
900         logger.debug("ServiceMain.createDefaultAccounts starting...");
901         
902         Hashtable<String, String> tenantInfo = getTenantNamesFromConfig(tenantBindingConfigReader);
903         Connection conn = null;
904         // TODO - need to put in tests for existence first.
905         // We could just look for the accounts per tenant up front, and assume that
906         // the rest is there if the accounts are.
907         // Could add a sql script to remove these if need be - Spring only does roles, 
908         // and we're not touching that, so we could safely toss the 
909         // accounts, users, account-tenants, account-roles, and start over.
910         try {
911                 conn = getConnection(cspaceDatabaseName);
912                 ArrayList<String> existingTenants = compileExistingTenants(conn, tenantInfo);
913                 
914                 // Note that this only creates tenants not marked as "createDisabled"
915                 createMissingTenants(conn, tenantInfo, existingTenants);
916                 
917                 ArrayList<String> usersInRepo = findOrCreateDefaultUsers(conn, tenantInfo);
918                 
919                 Hashtable<String, String> tenantAdminAcctCSIDs = new Hashtable<String, String>();
920                 Hashtable<String, String> tenantReaderAcctCSIDs = new Hashtable<String, String>();
921                 findOrCreateDefaultAccounts(conn, tenantInfo, usersInRepo,
922                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
923
924                 bindDefaultAccountsToTenants(conn, databaseProductType, tenantInfo, usersInRepo,
925                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
926                 
927                 Hashtable<String, String> tenantAdminRoleCSIDs = new Hashtable<String, String>();
928                 Hashtable<String, String> tenantReaderRoleCSIDs = new Hashtable<String, String>();
929                 String springAdminRoleCSID = findOrCreateDefaultRoles(conn, tenantInfo,
930                                 tenantAdminRoleCSIDs, tenantReaderRoleCSIDs);
931                 
932                 bindAccountsToRoles(conn,  databaseProductType,
933                                 tenantInfo, usersInRepo, springAdminRoleCSID,
934                                 tenantAdminRoleCSIDs, tenantReaderRoleCSIDs,
935                                 tenantAdminAcctCSIDs, tenantReaderAcctCSIDs);
936                 
937                 boolean createdTenantMgrAccount = findOrCreateTenantManagerUserAndAccount(conn);
938                 if(createdTenantMgrAccount) {
939                         // If we created the account, we need to create the bindings. Otherwise, assume they
940                         // are all set (from previous initialization).
941                         String tenantManagerRoleCSID = findTenantManagerRole(conn);
942                         bindTenantManagerAccountRole(conn, databaseProductType, 
943                                         TENANT_MANAGER_USER, AuthN.TENANT_MANAGER_ACCT_ID, 
944                                         tenantManagerRoleCSID, AuthN.ROLE_ALL_TENANTS_MANAGER);
945                 }
946         } catch (Exception e) {
947                         logger.debug("Exception in createDefaultAccounts: " + e.getLocalizedMessage());
948                 throw e;
949                 } finally {
950                         try {
951                                 if (conn != null)
952                                         conn.close();
953                         } catch (SQLException sqle) {
954                                 if (logger.isDebugEnabled()) {
955                                         logger.debug("SQL Exception closing statement/connection: " + sqle.getLocalizedMessage());
956                                 }
957                         }
958                 }       
959     }
960     
961     private static String getDefaultAdminRole(String tenantId) {
962         return ROLE_PREFIX+tenantId+TENANT_ADMIN_ROLE_SUFFIX;
963     }
964     
965     private static String getDefaultReaderRole(String tenantId) {
966         return ROLE_PREFIX+tenantId+TENANT_READER_ROLE_SUFFIX;
967     }
968     
969     private static String getDefaultAdminUserID(String tenantName) {
970         return TENANT_ADMIN_ACCT_PREFIX+tenantName;
971     }
972     
973     private static String getDefaultReaderUserID(String tenantName) {
974         return TENANT_READER_ACCT_PREFIX+tenantName;
975     }
976     
977         static public PermissionAction createPermissionAction(Permission perm,
978                         ActionType actionType) {
979         PermissionAction pa = new PermissionAction();
980
981             CSpaceAction action = URIResourceImpl.getAction(actionType);
982             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
983                     perm.getResourceName(), action);
984             pa.setName(actionType);
985             pa.setObjectIdentity(uriRes.getHashedId().toString());
986             pa.setObjectIdentityResource(uriRes.getId());
987             
988             return pa;
989         }
990
991         static public PermissionAction update(Permission perm, PermissionAction permAction) {
992         PermissionAction pa = new PermissionAction();
993
994             CSpaceAction action = URIResourceImpl.getAction(permAction.getName());
995             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),
996                     perm.getResourceName(), action);
997             pa.setObjectIdentity(uriRes.getHashedId().toString());
998             pa.setObjectIdentityResource(uriRes.getId());
999             
1000             return pa;
1001         }
1002         
1003         private static HashSet<String> getTransitionVerbList(TenantBindingType tenantBinding, ServiceBindingType serviceBinding) {
1004                 HashSet<String> result = new HashSet<String>();
1005                 
1006                 TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);
1007         for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {
1008                 String transitionVerb = transitionDef.getName();
1009                 String[] tokens = transitionVerb.split("_");  // Split the verb into words.  The workflow verbs are compound words combined with the '_' character.
1010                 result.add(tokens[0]); // We only care about the first word.
1011         }
1012
1013         return result;
1014         }
1015         
1016         private static TransitionDefList getTransitionDefList(TenantBindingType tenantBinding, ServiceBindingType serviceBinding) {
1017                 TransitionDefList result = null;
1018                 try {
1019                         String serviceObjectName = serviceBinding.getObject().getName();
1020                 DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance(
1021                                 tenantBinding, serviceBinding);
1022                 Lifecycle lifecycle = docHandler.getLifecycle(serviceObjectName);
1023                 if (lifecycle != null) {
1024                         result = lifecycle.getTransitionDefList();
1025                 }
1026                 } catch (Exception e) {
1027                         // Ignore this exception and return an empty non-null TransitionDefList
1028                 }
1029                 
1030                 if (result == null) {
1031                         if (serviceBinding.getType().equalsIgnoreCase(ServiceBindingUtils.SERVICE_TYPE_SECURITY) == false) {
1032                                 logger.debug("Could not retrieve a lifecycle transition definition list from: "
1033                                                 + serviceBinding.getName()
1034                                                 + " with tenant ID = "
1035                                                 + tenantBinding.getId());
1036                         }
1037                         // return an empty list                 
1038                         result = new TransitionDefList();
1039                 } else {
1040                         logger.debug("Successfully retrieved a lifecycle transition definition list from: "
1041                                         + serviceBinding.getName()
1042                                         + " with tenant ID = "
1043                                         + tenantBinding.getId());
1044                 }
1045                 
1046                 return result;
1047         }
1048         
1049     public static void createDefaultWorkflowPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception //FIXME: REM - 4/11/2012 - Rename to createWorkflowPermissions
1050     {
1051         AuthZ.get().login(); //login to Spring Security manager
1052         
1053         EntityManagerFactory emf = JpaStorageUtils.getEntityManagerFactory(JpaStorageUtils.CS_PERSISTENCE_UNIT);
1054         EntityManager em = null;
1055
1056         try {
1057             em = emf.createEntityManager();
1058
1059                 Hashtable<String, TenantBindingType> tenantBindings =
1060                         tenantBindingConfigReader.getTenantBindings();
1061                 for (String tenantId : tenantBindings.keySet()) {
1062                         logger.info(String.format("Creating/verifying workflow permissions for tenant ID=%s.", tenantId));
1063                         TenantBindingType tenantBinding = tenantBindings.get(tenantId);
1064                         Role adminRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_ADMINISTRATOR);
1065                         Role readonlyRole = AuthorizationCommon.getRole(em, tenantBinding.getId(), ROLE_TENANT_READER);
1066                         
1067                         if (adminRole == null || readonlyRole == null) {
1068                                 String msg = String.format("One or more of the required default CollectionSpace administrator roles is missing or was never created.  If you're setting up a new instance of CollectionSpace, shutdown the Tomcat server and run the 'ant import' command from the root/top level CollectionSpace 'Services' source directory.  Then try restarting Tomcat.");
1069                                 logger.error(msg);
1070                                 throw new RuntimeException("One or more of the required default CollectionSpace administrator roles is missing or was never created.");
1071                         }
1072                         
1073                         for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {
1074                                 String prop = ServiceBindingUtils.getPropertyValue(serviceBinding, REFRESH_AUTZ_PROP);
1075                                 if (prop == null ? true : Boolean.parseBoolean(prop)) {
1076                                                 try {
1077                                                 em.getTransaction().begin();
1078                                                 TransitionDefList transitionDefList = getTransitionDefList(tenantBinding, serviceBinding);
1079                                                 HashSet<String> transitionVerbList = getTransitionVerbList(tenantBinding, serviceBinding);
1080                                                 for (String transitionVerb : transitionVerbList) {
1081                                                         //
1082                                                         // Create the permission for the admin role
1083                                                         Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionVerb, ACTIONGROUP_CRUDL);
1084                                                         persist(em, adminPerm, adminRole, true, ACTIONGROUP_CRUDL);
1085                                                         //
1086                                                         // Create the permission for the read-only role
1087                                                         Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionVerb, ACTIONGROUP_RL);                                                      
1088                                                         persist(em, readonlyPerm, readonlyRole, true, ACTIONGROUP_RL); // Persist/store the permission and permrole records and related Spring Security info
1089                                                 }
1090                                                 em.getTransaction().commit();
1091                                         } catch (IllegalStateException e) {
1092                                                 logger.debug(e.getLocalizedMessage(), e); //We end up here if there is no document handler for the service -this is ok for some of the services.
1093                                         }
1094                                 } else {
1095                                         logger.warn("AuthZ refresh service binding property is set to FALSE so default permissions will NOT be refreshed for: "
1096                                                         + serviceBinding.getName());
1097                                 }
1098                         }
1099                 }
1100             em.close();
1101         } catch (Exception e) {
1102             if (em != null && em.getTransaction().isActive()) {
1103                 em.getTransaction().rollback();
1104             }
1105             if (logger.isDebugEnabled()) {
1106                 logger.debug("Caught exception and rolling back permission creation: ", e);
1107             }
1108             throw e;
1109         } finally {
1110             if (em != null) {
1111                 JpaStorageUtils.releaseEntityManagerFactory(emf);
1112             }
1113         }
1114     }
1115     
1116     private static PermissionRoleRel findPermRoleRel(EntityManager em, String permissionId, String RoleId) {
1117         PermissionRoleRel result = null;
1118         
1119         try {
1120                 String whereClause = "where permissionId = :id and roleId = :roleId";
1121                 HashMap<String, Object> params = new HashMap<String, Object>();
1122                 params.put("id", permissionId);
1123                 params.put("roleId", RoleId);        
1124         
1125                 result = (PermissionRoleRel) JpaStorageUtils.getEntity(em,
1126                                 PermissionRoleRel.class.getCanonicalName(), whereClause, params);
1127         } catch (Exception e) {
1128                 //Do nothing. Will return null;
1129         }
1130                 
1131         return result;
1132     }
1133     
1134     /*
1135      * Persists the Permission, PermissionRoleRel, and Spring Security table entries all in one transaction
1136      */
1137     private static void persist(EntityManager em, Permission permission, Role role, boolean enforceTenancy, ActionGroup actionGroup) throws Exception {
1138                 AuthorizationStore authzStore = new AuthorizationStore();
1139                 // First persist the Permission record
1140                 authzStore.store(em, permission);
1141                 
1142                 // If the PermRoleRel doesn't already exists then relate the permission and the role in a new PermissionRole (the service payload)
1143                 // Create a PermissionRoleRel (the database relation table for the permission and role)
1144                 PermissionRoleRel permRoleRel = findPermRoleRel(em, permission.getCsid(), role.getCsid());
1145                 if (permRoleRel == null) {
1146                         PermissionRole permRole = createPermissionRole(em, permission, role, enforceTenancy);
1147                 List<PermissionRoleRel> permRoleRels = new ArrayList<PermissionRoleRel>();
1148                 PermissionRoleUtil.buildPermissionRoleRel(em, permRole, SubjectType.ROLE, permRoleRels, false /*not for delete*/);
1149                 for (PermissionRoleRel prr : permRoleRels) {
1150                     authzStore.store(em, prr);
1151                 }
1152                         Profiler profiler = new Profiler(AuthorizationCommon.class, 2);
1153                         profiler.start();
1154                         // Add a corresponding entry in the Spring Security Tables
1155                         addPermissionsForUri(permission, permRole);
1156                         profiler.stop();
1157                         logger.debug("Finished full perm generation for "
1158                                         + ":" + permission.getTenantId()
1159                                         + ":" + permission.getResourceName()
1160                                         + ":" + actionGroup.getName()
1161                                         + ":" + profiler.getCumulativeTime());
1162                 }
1163         
1164     }
1165
1166 }