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