]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
45141ad0b5e22e3f3f0ce9710280699e2bc9224c
[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.Hashtable;\r
11 import java.util.List;\r
12 import java.util.UUID;\r
13 \r
14 import javax.naming.NamingException;\r
15 \r
16 import org.collectionspace.services.authorization.AuthZ;\r
17 import org.collectionspace.services.authorization.CSpaceAction;\r
18 import org.collectionspace.services.authorization.PermissionActionUtil;\r
19 import org.collectionspace.services.authorization.PermissionException;\r
20 import org.collectionspace.services.authorization.PermissionRole;\r
21 import org.collectionspace.services.authorization.PermissionValue;\r
22 import org.collectionspace.services.authorization.Role;\r
23 import org.collectionspace.services.authorization.RoleValue;\r
24 import org.collectionspace.services.authorization.SubjectType;\r
25 import org.collectionspace.services.authorization.URIResourceImpl;\r
26 import org.collectionspace.services.authorization.perms.ActionType;\r
27 import org.collectionspace.services.authorization.perms.EffectType;\r
28 import org.collectionspace.services.authorization.perms.Permission;\r
29 import org.collectionspace.services.authorization.perms.PermissionAction;\r
30 \r
31 import org.collectionspace.services.client.RoleClient;\r
32 import org.collectionspace.services.client.workflow.WorkflowClient;\r
33 \r
34 import org.collectionspace.services.common.authorization_mgt.AuthorizationStore;\r
35 import org.collectionspace.services.common.config.ServiceConfigUtils;\r
36 import org.collectionspace.services.common.config.TenantBindingConfigReaderImpl;\r
37 import org.collectionspace.services.common.document.DocumentHandler;\r
38 import org.collectionspace.services.common.security.SecurityUtils;\r
39 import org.collectionspace.services.common.service.ServiceBindingType;\r
40 import org.collectionspace.services.common.storage.DatabaseProductType;\r
41 import org.collectionspace.services.common.storage.JDBCTools;\r
42 import org.collectionspace.services.common.tenant.TenantBindingType;\r
43 \r
44 import org.collectionspace.services.lifecycle.Lifecycle;\r
45 import org.collectionspace.services.lifecycle.TransitionDef;\r
46 import org.collectionspace.services.lifecycle.TransitionDefList;\r
47 \r
48 //import org.mortbay.log.Log;\r
49 import org.slf4j.Logger;\r
50 import org.slf4j.LoggerFactory;\r
51 \r
52 import org.springframework.security.acls.model.AlreadyExistsException;\r
53 \r
54 \r
55 public class AuthorizationCommon {\r
56         \r
57     //\r
58     // ActionGroup labels/constants\r
59     //\r
60         \r
61         // for READ-WRITE\r
62     final public static String ACTIONGROUP_CRUDL_NAME = "CRUDL";\r
63     final public static ActionType[] ACTIONSET_CRUDL = {ActionType.CREATE, ActionType.READ, ActionType.UPDATE, ActionType.DELETE, ActionType.SEARCH};\r
64     // for READ-ONLY\r
65     final public static String ACTIONGROUP_RL_NAME = "RL";\r
66     final public static ActionType[] ACTIONSET_RL = {ActionType.READ, ActionType.SEARCH};\r
67     \r
68         /*\r
69          * Inner class to deal with predefined ADMIN and READER action groupds\r
70          */\r
71         public class ActionGroup {\r
72                 String name;\r
73                 ActionType[] actions;\r
74         }\r
75         \r
76         static ActionGroup ACTIONGROUP_CRUDL;\r
77         static ActionGroup ACTIONGROUP_RL;\r
78         \r
79         // A static block to initialize the predefined action groups\r
80         static {\r
81                 AuthorizationCommon ac = new AuthorizationCommon();\r
82                 // For admin\r
83                 ACTIONGROUP_CRUDL = ac.new ActionGroup();\r
84                 ACTIONGROUP_CRUDL.name = ACTIONGROUP_CRUDL_NAME;\r
85                 ACTIONGROUP_CRUDL.actions = ACTIONSET_CRUDL;\r
86                 // For reader\r
87                 ACTIONGROUP_RL = ac.new ActionGroup();\r
88                 ACTIONGROUP_RL.name = ACTIONGROUP_RL_NAME;\r
89                 ACTIONGROUP_RL.actions = ACTIONSET_RL;\r
90 \r
91         }\r
92         \r
93     final static Logger logger = LoggerFactory.getLogger(AuthorizationCommon.class);\r
94 \r
95     final public static String ROLE_ADMINISTRATOR = "ADMINISTRATOR";\r
96     final public static String ROLE_TENANT_ADMINISTRATOR = "TENANT_ADMINISTRATOR";\r
97     final public static String ROLE_TENANT_READER = "TENANT_READER";\r
98     final public static String ROLE_ADMINISTRATOR_ID = "0";\r
99     final public static String ADMINISTRATOR_TENANT_ID = "0";\r
100         \r
101     public static final String TENANT_ADMIN_ACCT_PREFIX = "admin@"; \r
102     public static final String TENANT_READER_ACCT_PREFIX = "reader@"; \r
103     public static final String ROLE_PREFIX = "ROLE_"; \r
104     public static final String SPRING_ADMIN_ROLE = "ROLE_SPRING_ADMIN"; \r
105     public static final String TENANT_ADMIN_ROLE_SUFFIX = "_TENANT_ADMINISTRATOR"; \r
106     public static final String TENANT_READER_ROLE_SUFFIX = "_TENANT_READER"; \r
107     public static final String DEFAULT_ADMIN_PASSWORD = "Administrator";\r
108     public static final String DEFAULT_READER_PASSWORD = "reader";\r
109 \r
110     public static String ROLE_SPRING_ADMIN_ID = "-1";\r
111     public static String ROLE_SPRING_ADMIN_NAME = "ROLE_SPRING_ADMIN";\r
112 \r
113     public static Role getRole(String tenantId, String displayName) {\r
114         Role role = null;\r
115         \r
116         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, displayName);\r
117         role = AuthorizationStore.getRoleByName(roleName, tenantId);\r
118         \r
119         return role;\r
120     }\r
121     \r
122     public static Role createRole(String tenantId, String name, String description) {\r
123         return createRole(tenantId, name, description, false /* mutable by default */);\r
124     }\r
125     \r
126     public static Role createRole(String tenantId, String name, String description, boolean immutable) {\r
127         Role role = new Role();\r
128         \r
129         role.setCreatedAtItem(new Date());\r
130         role.setDisplayName(name);\r
131         String roleName = AuthorizationCommon.getQualifiedRoleName(tenantId, name);     \r
132         role.setRoleName(roleName);\r
133         String id = UUID.randomUUID().toString(); //FIXME: The qualified role name should be unique enough to use as an ID/key\r
134         role.setCsid(id);\r
135                 role.setDescription(description);\r
136         role.setTenantId(tenantId);\r
137         if (immutable == true) {\r
138                 role.setMetadataProtection(RoleClient.IMMUTABLE);\r
139                 role.setPermsProtection(RoleClient.IMMUTABLE);\r
140         }\r
141         \r
142         return role;\r
143     }\r
144     \r
145     /**\r
146      * Add permission to the Spring Security tables\r
147      * with assumption that resource is of type URI\r
148      * @param permission configuration\r
149      */\r
150     public static void addPermissionsForUri(Permission perm,\r
151             PermissionRole permRole) throws PermissionException {\r
152         //\r
153         // First check the integrity of the incoming arguments.\r
154         //\r
155         if (!perm.getCsid().equals(permRole.getPermission().get(0).getPermissionId())) {\r
156             throw new IllegalArgumentException("permission ids do not"\r
157                     + " match for role=" + permRole.getRole().get(0).getRoleName()\r
158                     + " with permissionId=" + permRole.getPermission().get(0).getPermissionId()\r
159                     + " for permission with csid=" + perm.getCsid());\r
160         }\r
161         \r
162         List<String> principals = new ArrayList<String>();        \r
163         for (RoleValue roleValue : permRole.getRole()) {\r
164             principals.add(roleValue.getRoleName());\r
165         }\r
166         List<PermissionAction> permActions = perm.getAction();\r
167         for (PermissionAction permAction : permActions) {\r
168                 try {\r
169                     CSpaceAction action = URIResourceImpl.getAction(permAction.getName()); \r
170                     URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
171                             perm.getResourceName(), action);\r
172                     boolean grant = perm.getEffect().equals(EffectType.PERMIT) ? true : false;\r
173                     AuthZ.get().addPermissions(uriRes, principals.toArray(new String[0]), grant);//CSPACE-4967\r
174                 } catch (PermissionException e) {\r
175                         //\r
176                         // Only throw the exception if it is *not* an already-exists exception\r
177                         //\r
178                         if (e.getCause() instanceof AlreadyExistsException == false) {\r
179                                 throw e;\r
180                         }\r
181                 }\r
182         }\r
183     }\r
184     \r
185     private static Connection getConnection() throws NamingException, SQLException {\r
186         return JDBCTools.getConnection(JDBCTools.CSPACE_REPOSITORY_NAME);\r
187     }\r
188     \r
189     /*\r
190      * Spring security seems to require that all of our role names start\r
191      * with the ROLE_PREFIX string.\r
192      */\r
193     public static String getQualifiedRoleName(String tenantId, String name) {\r
194         String result = name;\r
195         \r
196         String qualifiedName = ROLE_PREFIX + tenantId.toUpperCase() + "_" + name.toUpperCase();         \r
197         if (name.equals(qualifiedName) == false) {\r
198                 result = qualifiedName;\r
199         }\r
200         \r
201         return result;\r
202     }\r
203         \r
204     private static ActionGroup getActionGroup(String actionGroupStr) {\r
205         ActionGroup result = null;\r
206         \r
207         if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_CRUDL_NAME)) {\r
208                 result = ACTIONGROUP_CRUDL;\r
209         } else if (actionGroupStr.equalsIgnoreCase(ACTIONGROUP_RL_NAME)) {\r
210                 result = ACTIONGROUP_RL;\r
211         }\r
212         \r
213         return result;\r
214     }\r
215     \r
216     public static Permission createPermission(String tenantId,\r
217                 String resourceName,\r
218                 String description,\r
219                 String actionGroupStr) {\r
220         Permission result = null;\r
221         \r
222         ActionGroup actionGroup = getActionGroup(actionGroupStr);\r
223         result = createPermission(tenantId, resourceName, description, actionGroup);\r
224         \r
225         return result;\r
226     }\r
227     \r
228     private static Permission createPermission(String tenantId,\r
229                 String resourceName,\r
230                 String description,\r
231                 ActionGroup actionGroup) {\r
232         String id = UUID.randomUUID().toString(); //FIXME: Could this be something like a refname instead of a UUID?\r
233         Permission perm = new Permission();\r
234         perm.setCsid(id);\r
235         perm.setDescription(description);\r
236         perm.setCreatedAtItem(new Date());\r
237         perm.setResourceName(resourceName.toLowerCase().trim());\r
238         perm.setEffect(EffectType.PERMIT);\r
239         perm.setTenantId(tenantId);\r
240         \r
241         perm.setActionGroup(actionGroup.name);\r
242         ArrayList<PermissionAction> pas = new ArrayList<PermissionAction>();\r
243         perm.setAction(pas);\r
244         for (ActionType actionType : actionGroup.actions) {\r
245                 PermissionAction permAction = createPermissionAction(perm, actionType);\r
246                 pas.add(permAction);\r
247         }\r
248         \r
249         return perm;\r
250     }\r
251     \r
252     private static Permission createWorkflowPermission(TenantBindingType tenantBinding,\r
253                 ServiceBindingType serviceBinding,\r
254                 TransitionDef transitionDef,\r
255                 ActionGroup actionGroup)\r
256     {\r
257         Permission result = null;\r
258         \r
259         String tenantId = tenantBinding.getId();\r
260         String resourceName = serviceBinding.getName().toLowerCase().trim()\r
261                         + WorkflowClient.SERVICE_AUTHZ_SUFFIX\r
262                         + transitionDef.getName();\r
263         String description = "A generate workflow permission for actiongroup " + actionGroup.name;\r
264         result = createPermission(tenantId, resourceName, description, actionGroup);\r
265         \r
266         return result;\r
267     }\r
268     \r
269     private static PermissionRole createPermissionRole(Permission permission,\r
270                 Role role,\r
271                 boolean enforceTenancy) throws Exception\r
272     {\r
273         PermissionRole permRole = new PermissionRole();\r
274         \r
275                 if (enforceTenancy && role.getTenantId().equalsIgnoreCase(permission.getTenantId())) {\r
276                 permRole.setSubject(SubjectType.ROLE);\r
277                 //\r
278                 // Set of the permission value list of the permrole\r
279                 //\r
280                 List<PermissionValue> permValues = new ArrayList<PermissionValue>();\r
281                 PermissionValue permValue = new PermissionValue();\r
282                 permValue.setPermissionId(permission.getCsid());\r
283                 permValue.setResourceName(permission.getResourceName().toLowerCase());\r
284                 permValue.setActionGroup(permission.getActionGroup());\r
285                 permValues.add(permValue);\r
286                 permRole.setPermission(permValues);\r
287                 //\r
288                 // Set of the role value list of the permrole\r
289                 //\r
290                 List<RoleValue> roleValues = new ArrayList<RoleValue>();\r
291                 RoleValue rv = new RoleValue();\r
292             // This needs to use the qualified name, not the display name\r
293             rv.setRoleName(role.getRoleName());\r
294             rv.setRoleId(role.getCsid());\r
295             roleValues.add(rv);\r
296             permRole.setRole(roleValues);\r
297                 } else {\r
298                 String errMsg = "The tenant ID of the role: " + role.getTenantId()\r
299                                 + " did not match the tenant ID of the permission: " + permission.getTenantId();\r
300                 throw new Exception(errMsg);\r
301                 }\r
302         \r
303         return permRole;\r
304     }\r
305     \r
306     public static void createDefaultPermissions(TenantBindingConfigReaderImpl tenantBindingConfigReader) throws Exception\r
307     {\r
308         PermissionAction pa = new PermissionAction();\r
309         pa.getHjid();\r
310 \r
311         Hashtable<String, TenantBindingType> tenantBindings =\r
312                 tenantBindingConfigReader.getTenantBindings();\r
313         for (String tenantId : tenantBindings.keySet()) {\r
314                 TenantBindingType tenantBinding = tenantBindings.get(tenantId);\r
315                 for (ServiceBindingType serviceBinding : tenantBinding.getServiceBindings()) {\r
316                         try {\r
317                                 DocumentHandler docHandler = ServiceConfigUtils.createDocumentHandlerInstance(\r
318                                                 tenantBinding, serviceBinding);\r
319                                 Lifecycle lifecycle = docHandler.getLifecycle();\r
320                                 TransitionDefList transitionDefList = lifecycle.getTransitionDefList();\r
321                                 for (TransitionDef transitionDef : transitionDefList.getTransitionDef()) {\r
322                                         //\r
323                                         // Create the permission for the admin role\r
324                                         //\r
325                                         Permission adminPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, AuthorizationCommon.ACTIONGROUP_CRUDL);\r
326                                         Role adminRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_ADMINISTRATOR);\r
327                                         PermissionRole adminPermRole = createPermissionRole(adminPerm, adminRole, true);\r
328                                         addPermissionsForUri(adminPerm, adminPermRole);\r
329                                         //\r
330                                         // Create the permission for the read-only role\r
331                                         Permission readonlyPerm = createWorkflowPermission(tenantBinding, serviceBinding, transitionDef, AuthorizationCommon.ACTIONGROUP_RL);\r
332                                         Role readonlyRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_READER);\r
333                                         PermissionRole readonlyPermRole = createPermissionRole(readonlyPerm, readonlyRole, true);\r
334                                         addPermissionsForUri(readonlyPerm, readonlyPermRole);\r
335                                         //\r
336                                         // Create the permission for the super-admin role.  Note we use the same "adminPerm" instance we used for the "adminPermRole" instance\r
337                                         //\r
338                                         Role superRole = AuthorizationCommon.getRole(tenantBinding.getId(), AuthorizationCommon.ROLE_TENANT_READER);\r
339                                         PermissionRole superPermRole = createPermissionRole(adminPerm, superRole, false);\r
340                                         addPermissionsForUri(adminPerm, superPermRole);\r
341                                 }\r
342                         } catch (IllegalStateException e) {\r
343                                 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
344                         }\r
345                 }\r
346         }\r
347     }\r
348     \r
349     /*\r
350      * FIXME: REM - This method is way too big -over 300 lines!  We need to break it up into\r
351      * smaller, discrete, sub-methods.\r
352      */\r
353     public static void createDefaultAccounts(TenantBindingConfigReaderImpl tenantBindingConfigReader) {\r
354         if (logger.isDebugEnabled()) {\r
355                 logger.debug("ServiceMain.createDefaultAccounts starting...");\r
356         }\r
357         \r
358         Hashtable<String, TenantBindingType> tenantBindings =\r
359                 tenantBindingConfigReader.getTenantBindings();\r
360         Hashtable<String, String> tenantInfo = new Hashtable<String, String>();\r
361         for (TenantBindingType tenantBinding : tenantBindings.values()) {\r
362                 String tId = tenantBinding.getId();\r
363                 String tName = tenantBinding.getName();\r
364                 tenantInfo.put(tId, tName);\r
365                 if (logger.isDebugEnabled()) {\r
366                         logger.debug("createDefaultAccounts found configured tenant id: "+tId+" name: "+tName);\r
367                 }\r
368         }\r
369         Connection conn = null;\r
370         PreparedStatement pstmt = null;\r
371         Statement stmt = null;\r
372         // TODO - need to put in tests for existence first.\r
373         // We could just look for the accounts per tenant up front, and assume that\r
374         // the rest is there if the accounts are.\r
375         // Could add a sql script to remove these if need be - Spring only does roles, \r
376         // and we're not touching that, so we could safely toss the \r
377         // accounts, users, account-tenants, account-roles, and start over.\r
378         try {\r
379                 conn = getConnection();\r
380                 // First find or create the tenants\r
381                 String queryTenantSQL = \r
382                         "SELECT id,name FROM tenants";\r
383                 stmt = conn.createStatement();\r
384                         ResultSet rs = stmt.executeQuery(queryTenantSQL);\r
385                 ArrayList<String> existingTenants = new ArrayList<String>();\r
386                         while (rs.next()) {\r
387                                 String tId = rs.getString("id");\r
388                                 String tName = rs.getString("name");\r
389                                 if(tenantInfo.containsKey(tId)) {\r
390                                         existingTenants.add(tId);\r
391                                         if(!tenantInfo.get(tId).equalsIgnoreCase(tName)) {\r
392                                                 logger.warn("Configured name for tenant: "\r
393                                                                 +tId+" in repository: "+tName\r
394                                                                 +" does not match config'd name: "+ tenantInfo.get(tId));\r
395                                         }\r
396                                 }\r
397                         }\r
398                         rs.close();\r
399 \r
400                 String insertTenantSQL = \r
401                         "INSERT INTO tenants (id,name,created_at) VALUES (?,?, now())";\r
402                 pstmt = conn.prepareStatement(insertTenantSQL); // create a statement\r
403                 for(String tId : tenantInfo.keySet()) {\r
404                         if(existingTenants.contains(tId)) {\r
405                         if (logger.isDebugEnabled()) {\r
406                                 logger.debug("createDefaultAccounts: tenant exists (skipping): "\r
407                                                 +tenantInfo.get(tId));\r
408                         }\r
409                                 continue;\r
410                         }\r
411                         pstmt.setString(1, tId);                                        // set id param\r
412                         pstmt.setString(2, tenantInfo.get(tId));        // set name param\r
413                 if (logger.isDebugEnabled()) {\r
414                         logger.debug("createDefaultAccounts adding entry for tenant: "+tId);\r
415                 }\r
416                         pstmt.executeUpdate();\r
417                 }\r
418                 pstmt.close();\r
419                 // Second find or create the users\r
420                 String queryUserSQL = \r
421                         "SELECT username FROM users WHERE username LIKE '"\r
422                                 +TENANT_ADMIN_ACCT_PREFIX+"%' OR username LIKE '"\r
423                                 +TENANT_READER_ACCT_PREFIX+"%'";\r
424                         rs = stmt.executeQuery(queryUserSQL);\r
425                 ArrayList<String> usersInRepo = new ArrayList<String>();\r
426                         while (rs.next()) {\r
427                                 String uName = rs.getString("username");\r
428                                 usersInRepo.add(uName);\r
429                         }\r
430                         rs.close();\r
431                 String insertUserSQL = \r
432                         "INSERT INTO users (username,passwd, created_at)"\r
433                         +" VALUES (?,?, now())";\r
434                 pstmt = conn.prepareStatement(insertUserSQL); // create a statement\r
435                 for(String tName : tenantInfo.values()) {\r
436                         String adminAcctName = getDefaultAdminUserID(tName);\r
437                         if(!usersInRepo.contains(adminAcctName)) {\r
438                                 String secEncPasswd = SecurityUtils.createPasswordHash(\r
439                                                 adminAcctName, DEFAULT_ADMIN_PASSWORD);\r
440                                 pstmt.setString(1, adminAcctName);      // set username param\r
441                                 pstmt.setString(2, secEncPasswd);       // set passwd param\r
442                         if (logger.isDebugEnabled()) {\r
443                                 logger.debug("createDefaultAccounts adding user: "\r
444                                                 +adminAcctName+" for tenant: "+tName);\r
445                         }\r
446                                 pstmt.executeUpdate();\r
447                         } else if (logger.isDebugEnabled()) {\r
448                         logger.debug("createDefaultAccounts: user: "+adminAcctName\r
449                                                         +" already exists - skipping.");\r
450                 }\r
451 \r
452 \r
453                         String readerAcctName =  getDefaultReaderUserID(tName);\r
454                         if(!usersInRepo.contains(readerAcctName)) {\r
455                                 String secEncPasswd = SecurityUtils.createPasswordHash(\r
456                                                 readerAcctName, DEFAULT_READER_PASSWORD);\r
457                                 pstmt.setString(1, readerAcctName);     // set username param\r
458                                 pstmt.setString(2, secEncPasswd);       // set passwd param\r
459                         if (logger.isDebugEnabled()) {\r
460                                 logger.debug("createDefaultAccounts adding user: "\r
461                                                 +readerAcctName+" for tenant: "+tName);\r
462                         }\r
463                                 pstmt.executeUpdate();\r
464                         } else if (logger.isDebugEnabled()) {\r
465                         logger.debug("createDefaultAccounts: user: "+readerAcctName\r
466                                                         +" already exists - skipping.");\r
467                         }\r
468                 }\r
469                 pstmt.close();\r
470                 // Third, create the accounts. Assume that if the users were already there,\r
471                 // then the accounts were as well\r
472             String insertAccountSQL = \r
473                 "INSERT INTO accounts_common "\r
474                 + "(csid, email, userid, status, screen_name, metadata_protection, roles_protection, created_at) "\r
475                 + "VALUES (?,?,?,'ACTIVE',?, 'immutable', 'immutable', now())";\r
476             Hashtable<String, String> tenantAdminAcctCSIDs = new Hashtable<String, String>();\r
477             Hashtable<String, String> tenantReaderAcctCSIDs = new Hashtable<String, String>();\r
478                 pstmt = conn.prepareStatement(insertAccountSQL); // create a statement\r
479                 for(String tId : tenantInfo.keySet()) {\r
480                         String tName = tenantInfo.get(tId);\r
481                 String adminCSID = UUID.randomUUID().toString();\r
482                 tenantAdminAcctCSIDs.put(tId, adminCSID);\r
483                         String adminAcctName =  getDefaultAdminUserID(tName);\r
484                         if(!usersInRepo.contains(adminAcctName)) {\r
485                                 pstmt.setString(1, adminCSID);                  // set csid param\r
486                                 pstmt.setString(2, adminAcctName);      // set email param (bogus)\r
487                                 pstmt.setString(3, adminAcctName);      // set userid param\r
488                                 pstmt.setString(4, "Administrator");// set screen name param\r
489                         if (logger.isDebugEnabled()) {\r
490                                 logger.debug("createDefaultAccounts adding account: "\r
491                                                 +adminAcctName+" for tenant: "+tName);\r
492                         }\r
493                                 pstmt.executeUpdate();\r
494                         } else if (logger.isDebugEnabled()) {\r
495                         logger.debug("createDefaultAccounts: user: "+adminAcctName\r
496                                                         +" already exists - skipping account generation.");\r
497                         }\r
498 \r
499                         String readerCSID = UUID.randomUUID().toString();       \r
500                 tenantReaderAcctCSIDs.put(tId, readerCSID);\r
501                         String readerAcctName =  getDefaultReaderUserID(tName);\r
502                         if(!usersInRepo.contains(readerAcctName)) {\r
503                                 pstmt.setString(1, readerCSID);         // set csid param\r
504                                 pstmt.setString(2, readerAcctName);     // set email param (bogus)\r
505                                 pstmt.setString(3, readerAcctName);     // set userid param\r
506                                 pstmt.setString(4, "Reader");           // set screen name param\r
507                                 if (logger.isDebugEnabled()) {\r
508                                         logger.debug("createDefaultAccounts adding account: "\r
509                                                         +readerAcctName+" for tenant: "+tName);\r
510                                 }\r
511                                 pstmt.executeUpdate();\r
512                         } else if (logger.isDebugEnabled()) {\r
513                         logger.debug("createDefaultAccounts: user: "+readerAcctName\r
514                                                         +" already exists - skipping account creation.");\r
515                         }\r
516                 }\r
517                 pstmt.close();\r
518                 // Fourth, bind accounts to tenants. Assume that if the users were already there,\r
519                 // then the accounts were bound to tenants correctly\r
520                 String insertAccountTenantSQL;\r
521                 DatabaseProductType databaseProductType = JDBCTools.getDatabaseProductType();\r
522                 if (databaseProductType == DatabaseProductType.MYSQL) {\r
523                         insertAccountTenantSQL =\r
524                                 "INSERT INTO accounts_tenants (TENANTS_ACCOUNTSCOMMON_CSID,tenant_id) "\r
525                                 + " VALUES(?, ?)";\r
526                 } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
527                         insertAccountTenantSQL =\r
528                                 "INSERT INTO accounts_tenants (HJID, TENANTS_ACCOUNTSCOMMON_CSID,tenant_id) "\r
529                                 + " VALUES(nextval('hibernate_sequence'), ?, ?)";\r
530                 } else {\r
531                         throw new Exception("Unrecognized database system.");\r
532                 }\r
533                 pstmt = conn.prepareStatement(insertAccountTenantSQL); // create a statement\r
534                 for(String tId : tenantInfo.keySet()) {\r
535                         String tName = tenantInfo.get(tId);\r
536                         if(!usersInRepo.contains(getDefaultAdminUserID(tName))) {\r
537                                 String adminAcct = tenantAdminAcctCSIDs.get(tId);\r
538                                 pstmt.setString(1, adminAcct);          // set acct CSID param\r
539                                 pstmt.setString(2, tId);                        // set tenant_id param\r
540                         if (logger.isDebugEnabled()) {\r
541                                 logger.debug("createDefaultAccounts binding account id: "\r
542                                                 +adminAcct+" to tenant id: "+tId);\r
543                         }\r
544                                 pstmt.executeUpdate();\r
545                         }\r
546                         if(!usersInRepo.contains(getDefaultReaderUserID(tName))) {\r
547                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);\r
548                                 pstmt.setString(1, readerAcct);         // set acct CSID param\r
549                                 pstmt.setString(2, tId);                        // set tenant_id param\r
550                         if (logger.isDebugEnabled()) {\r
551                                 logger.debug("createDefaultAccounts binding account id: "\r
552                                                 +readerAcct+" to tenant id: "+tId);\r
553                         }\r
554                                 pstmt.executeUpdate();\r
555                         }\r
556                 }\r
557                 pstmt.close();\r
558                 // Fifth, fetch and save the default roles\r
559                         String springAdminRoleCSID = null;\r
560                 String querySpringRole = \r
561                         "SELECT csid from roles WHERE rolename='"+SPRING_ADMIN_ROLE+"'";\r
562                         rs = stmt.executeQuery(querySpringRole);\r
563                 if(rs.next()) {\r
564                         springAdminRoleCSID = rs.getString(1);\r
565                 if (logger.isDebugEnabled()) {\r
566                         logger.debug("createDefaultAccounts found Spring Admin role: "\r
567                                         +springAdminRoleCSID);\r
568                 }\r
569                 } else {\r
570                 String insertSpringAdminRoleSQL =\r
571                         "INSERT INTO roles (csid, rolename, displayName, rolegroup, created_at, tenant_id) "\r
572                         + "VALUES ('-1', 'ROLE_SPRING_ADMIN', 'SPRING_ADMIN', 'Spring Security Administrator', now(), '0')";\r
573                         stmt.executeUpdate(insertSpringAdminRoleSQL);\r
574                         springAdminRoleCSID = "-1";\r
575                 if (logger.isDebugEnabled()) {\r
576                         logger.debug("createDefaultAccounts CREATED Spring Admin role: "\r
577                                         +springAdminRoleCSID);\r
578                 }\r
579                 }\r
580                 rs.close();\r
581                 String getRoleCSIDSql =\r
582                         "SELECT csid from roles WHERE tenant_id=? and rolename=?";\r
583                 pstmt = conn.prepareStatement(getRoleCSIDSql); // create a statement\r
584                 rs = null;\r
585             Hashtable<String, String> tenantAdminRoleCSIDs = new Hashtable<String, String>();\r
586             Hashtable<String, String> tenantReaderRoleCSIDs = new Hashtable<String, String>();\r
587                 for(String tId : tenantInfo.keySet()) {\r
588                         pstmt.setString(1, tId);                                                // set tenant_id param\r
589                         pstmt.setString(2, getDefaultAdminRole(tId));   // set rolename param\r
590                         rs = pstmt.executeQuery();\r
591                         // extract data from the ResultSet\r
592                         if(!rs.next()) {\r
593                                 throw new RuntimeException("Cannot find role: "+getDefaultAdminRole(tId)\r
594                                                 +" for tenant id: "+tId+" in roles!");\r
595                         }\r
596                         String tenantAdminRoleCSID = rs.getString(1);\r
597                 if (logger.isDebugEnabled()) {\r
598                         logger.debug("createDefaultAccounts found role: "\r
599                                         +getDefaultAdminRole(tId)+"("+tenantAdminRoleCSID\r
600                                         +") for tenant id: "+tId);\r
601                 }\r
602                         tenantAdminRoleCSIDs.put(tId, tenantAdminRoleCSID);\r
603                         pstmt.setString(1, tId);                                                // set tenant_id param\r
604                         pstmt.setString(2, getDefaultReaderRole(tId));  // set rolename param\r
605                         rs.close();\r
606                         rs = pstmt.executeQuery();\r
607                         // extract data from the ResultSet\r
608                         if(!rs.next()) {\r
609                                 throw new RuntimeException("Cannot find role: "+getDefaultReaderRole(tId)\r
610                                                 +" for tenant id: "+tId+" in roles!");\r
611                         }\r
612                         String tenantReaderRoleCSID = rs.getString(1);\r
613                 if (logger.isDebugEnabled()) {\r
614                         logger.debug("createDefaultAccounts found role: "\r
615                                         +getDefaultReaderRole(tId)+"("+tenantReaderRoleCSID\r
616                                         +") for tenant id: "+tId);\r
617                 }\r
618                         tenantReaderRoleCSIDs.put(tId, tenantReaderRoleCSID);\r
619                         rs.close();\r
620                 }\r
621                 pstmt.close();\r
622                 // Sixth, bind the accounts to roles. If the users already existed,\r
623                 // we'll assume they were set up correctly.\r
624                                         String insertAccountRoleSQL;\r
625                                         if (databaseProductType == DatabaseProductType.MYSQL) {\r
626                                                 insertAccountRoleSQL =\r
627                                                 "INSERT INTO accounts_roles(account_id, user_id, role_id, role_name, created_at)"\r
628                                                         +" VALUES(?, ?, ?, ?, now())";\r
629                                         } else if (databaseProductType == DatabaseProductType.POSTGRESQL) {\r
630                                                 insertAccountRoleSQL =\r
631                                                 "INSERT INTO accounts_roles(HJID, account_id, user_id, role_id, role_name, created_at)"\r
632                                                         +" VALUES(nextval('hibernate_sequence'), ?, ?, ?, ?, now())";\r
633                                         } else {\r
634                                                         throw new Exception("Unrecognized database system.");\r
635                                         }\r
636                 if (logger.isDebugEnabled()) {\r
637                         logger.debug("createDefaultAccounts binding accounts to roles with SQL:\n"\r
638                                         +insertAccountRoleSQL);\r
639                 }\r
640                 pstmt = conn.prepareStatement(insertAccountRoleSQL); // create a statement\r
641                 for(String tId : tenantInfo.keySet()) {\r
642                         String adminUserId =  getDefaultAdminUserID(tenantInfo.get(tId));\r
643                         if(!usersInRepo.contains(adminUserId)) {\r
644                         String adminAcct = tenantAdminAcctCSIDs.get(tId);\r
645                                 String adminRoleId = tenantAdminRoleCSIDs.get(tId);\r
646                                 pstmt.setString(1, adminAcct);          // set acct CSID param\r
647                                 pstmt.setString(2, adminUserId);        // set user_id param\r
648                                 pstmt.setString(3, adminRoleId);        // set role_id param\r
649                                 pstmt.setString(4, getDefaultAdminRole(tId));   // set rolename param\r
650                         if (logger.isDebugEnabled()) {\r
651                                 logger.debug("createDefaultAccounts binding account: "\r
652                                                 +adminUserId+" to Admin role("+adminRoleId\r
653                                                 +") for tenant id: "+tId);\r
654                         }\r
655                                 pstmt.executeUpdate();\r
656                                 // Now add the Spring Admin Role to the admin accounts\r
657                                 pstmt.setString(3, springAdminRoleCSID);        // set role_id param\r
658                                 pstmt.setString(4, SPRING_ADMIN_ROLE);          // set rolename param\r
659                         if (logger.isDebugEnabled()) {\r
660                                 logger.debug("createDefaultAccounts binding account: "\r
661                                                 +adminUserId+" to Spring Admin role: "+springAdminRoleCSID);\r
662                         }\r
663                                 pstmt.executeUpdate();\r
664                         }\r
665                         String readerUserId = getDefaultReaderUserID(tenantInfo.get(tId));\r
666                         if(!usersInRepo.contains(readerUserId)) {\r
667                                 String readerAcct = tenantReaderAcctCSIDs.get(tId);\r
668                                 String readerRoleId = tenantReaderRoleCSIDs.get(tId);\r
669                                 pstmt.setString(1, readerAcct);         // set acct CSID param\r
670                                 pstmt.setString(2, readerUserId);       // set user_id param\r
671                                 pstmt.setString(3, readerRoleId);       // set role_id param\r
672                                 pstmt.setString(4, getDefaultReaderRole(tId));  // set rolename param\r
673                         if (logger.isDebugEnabled()) {\r
674                                 logger.debug("createDefaultAccounts binding account: "\r
675                                                 +readerUserId+" to Reader role("+readerRoleId\r
676                                                 +") for tenant id: "+tId);\r
677                         }\r
678                                 pstmt.executeUpdate();\r
679                         }\r
680                 }\r
681                 pstmt.close();\r
682                         stmt.close();\r
683         } catch (RuntimeException rte) {\r
684                 if (logger.isDebugEnabled()) {\r
685                         logger.debug("Exception in createDefaultAccounts: "+\r
686                                                 rte.getLocalizedMessage());\r
687                         logger.debug(rte.getStackTrace().toString());\r
688                 }\r
689             throw rte;\r
690         } catch (SQLException sqle) {\r
691             // SQLExceptions can be chained. We have at least one exception, so\r
692             // set up a loop to make sure we let the user know about all of them\r
693             // if there happens to be more than one.\r
694                 if (logger.isDebugEnabled()) {\r
695                         SQLException tempException = sqle;\r
696                         while (null != tempException) {\r
697                                 logger.debug("SQL Exception: " + sqle.getLocalizedMessage());\r
698                                 tempException = tempException.getNextException();\r
699                         }\r
700                         logger.debug(sqle.getStackTrace().toString());\r
701                 }\r
702             throw new RuntimeException("SQL problem in createDefaultAccounts: ", sqle);\r
703         } catch (Exception e) {\r
704                 if (logger.isDebugEnabled()) {\r
705                         logger.debug("Exception in createDefaultAccounts: "+\r
706                                                 e.getLocalizedMessage());\r
707                 }\r
708         } finally {\r
709                 try {\r
710                 if(conn!=null)\r
711                     conn.close();\r
712                 if(pstmt!=null)\r
713                     pstmt.close();\r
714                 if(stmt!=null)\r
715                     stmt.close();\r
716             } catch (SQLException sqle) {\r
717                 if (logger.isDebugEnabled()) {\r
718                                 logger.debug("SQL Exception closing statement/connection: "\r
719                                                 + sqle.getLocalizedMessage());\r
720                 }\r
721                 }\r
722         }       \r
723     }\r
724     \r
725     private static String getDefaultAdminRole(String tenantId) {\r
726         return ROLE_PREFIX+tenantId+TENANT_ADMIN_ROLE_SUFFIX;\r
727     }\r
728     \r
729     private static String getDefaultReaderRole(String tenantId) {\r
730         return ROLE_PREFIX+tenantId+TENANT_READER_ROLE_SUFFIX;\r
731     }\r
732     \r
733     private static String getDefaultAdminUserID(String tenantName) {\r
734         return TENANT_ADMIN_ACCT_PREFIX+tenantName;\r
735     }\r
736     \r
737     private static String getDefaultReaderUserID(String tenantName) {\r
738         return TENANT_READER_ACCT_PREFIX+tenantName;\r
739     }\r
740     \r
741         static public PermissionAction createPermissionAction(Permission perm,\r
742                         ActionType actionType) {\r
743         PermissionAction pa = new PermissionAction();\r
744 \r
745             CSpaceAction action = URIResourceImpl.getAction(actionType);\r
746             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
747                     perm.getResourceName(), action);\r
748             pa.setName(actionType);\r
749             pa.setObjectIdentity(uriRes.getHashedId().toString());\r
750             pa.setObjectIdentityResource(uriRes.getId());\r
751             \r
752             return pa;\r
753         }\r
754 \r
755         static public PermissionAction update(Permission perm, PermissionAction permAction) {\r
756         PermissionAction pa = new PermissionAction();\r
757 \r
758             CSpaceAction action = URIResourceImpl.getAction(permAction.getName());\r
759             URIResourceImpl uriRes = new URIResourceImpl(perm.getTenantId(),\r
760                     perm.getResourceName(), action);\r
761             pa.setObjectIdentity(uriRes.getHashedId().toString());\r
762             pa.setObjectIdentityResource(uriRes.getId());\r
763             \r
764             return pa;\r
765         }\r
766         \r
767         \r
768 \r
769 }\r