1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jetspeed.services.security.turbine;
18
19 import java.sql.Connection;
20 import java.util.HashMap;
21 import java.util.Iterator;
22 import java.util.List;
23
24 import javax.servlet.ServletConfig;
25
26 import org.apache.jetspeed.om.profile.Profile;
27 import org.apache.jetspeed.om.profile.ProfileException;
28 import org.apache.jetspeed.om.security.BaseJetspeedGroupRole;
29 import org.apache.jetspeed.om.security.Group;
30 import org.apache.jetspeed.om.security.GroupRole;
31 import org.apache.jetspeed.om.security.JetspeedUser;
32 import org.apache.jetspeed.om.security.Role;
33 import org.apache.jetspeed.om.security.UserNamePrincipal;
34 import org.apache.jetspeed.om.security.turbine.TurbineRole;
35 import org.apache.jetspeed.om.security.turbine.TurbineRolePeer;
36 import org.apache.jetspeed.om.security.turbine.TurbineRolePermissionPeer;
37 import org.apache.jetspeed.om.security.turbine.TurbineUserGroupRole;
38 import org.apache.jetspeed.om.security.turbine.TurbineUserGroupRolePeer;
39 import org.apache.jetspeed.services.JetspeedSecurity;
40 import org.apache.jetspeed.services.Profiler;
41 import org.apache.jetspeed.services.PsmlManager;
42 import org.apache.jetspeed.services.rundata.JetspeedRunData;
43 import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
44 import org.apache.jetspeed.services.security.CachedAcl;
45 import org.apache.jetspeed.services.security.GroupManagement;
46 import org.apache.jetspeed.services.security.JetspeedSecurityCache;
47 import org.apache.jetspeed.services.security.JetspeedSecurityException;
48 import org.apache.jetspeed.services.security.JetspeedSecurityService;
49 import org.apache.jetspeed.services.security.RoleException;
50 import org.apache.jetspeed.services.security.RoleManagement;
51 import org.apache.torque.Torque;
52 import org.apache.torque.om.NumberKey;
53 import org.apache.torque.util.Criteria;
54 import org.apache.turbine.services.InitializationException;
55 import org.apache.turbine.services.TurbineBaseService;
56 import org.apache.turbine.services.TurbineServices;
57 import org.apache.turbine.services.resources.ResourceService;
58 import org.apache.turbine.services.rundata.RunDataService;
59 import org.apache.turbine.util.Log;
60
61 /***
62 * Default Jetspeed-Turbine Role Management implementation
63 *
64 *
65 * @author <a href="mailto:david@bluesunrise.com">David Sean Taylor</a>
66 * @author <a href="mailto:morciuch@apache.org">Mark Orciuch</a>
67 * @version $Id: TurbineRoleManagement.java,v 1.14 2004/02/23 03:54:49 jford Exp $
68 */
69
70 public class TurbineRoleManagement extends TurbineBaseService
71 implements RoleManagement
72 {
73 private JetspeedRunDataService runDataService = null;
74 private final static String CASCADE_DELETE = "programmatic.cascade.delete";
75 private final static boolean DEFAULT_CASCADE_DELETE = true;
76 private boolean cascadeDelete;
77 private final static String CACHING_ENABLE = "caching.enable";
78 private boolean cachingEnable = true;
79
80
81
82
83
84
85 /***
86 * Retrieves all <code>Role</code>s for a given username principal.
87 *
88 * The security service may optionally check the current user context
89 * to determine if the requestor has permission to perform this action.
90 *
91 * @param username a user principal identity to be retrieved.
92 * @return Iterator over all roles associated to the user principal (iterator of GroupRole objects keyed on group+role).
93 * @exception RoleException when the security provider has a general failure.
94 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
95 */
96 public Iterator getRoles(String username)
97 throws JetspeedSecurityException
98 {
99 JetspeedUser user = null;
100 try
101 {
102 if (cachingEnable)
103 {
104 Iterator result = JetspeedSecurityCache.getRoles(username);
105 if (null != result)
106 {
107 return result;
108 }
109 }
110 user = JetspeedSecurity.getUser(new UserNamePrincipal(username));
111 }
112 catch(JetspeedSecurityException e)
113 {
114 throw new RoleException("Failed to Retrieve User: ", e);
115 }
116 Criteria criteria = new Criteria();
117 criteria.add(TurbineUserGroupRolePeer.USER_ID, user.getUserId());
118 List rels;
119 HashMap roles;
120
121 try
122 {
123 rels = TurbineUserGroupRolePeer.doSelect(criteria);
124 if (rels.size() > 0)
125 {
126 roles = new HashMap(rels.size());
127 }
128 else
129 {
130 roles = new HashMap();
131 }
132
133 for (int ix = 0; ix < rels.size(); ix++)
134 {
135 TurbineUserGroupRole rel = (TurbineUserGroupRole) rels.get(ix);
136 Role role = rel.getTurbineRole();
137 Group group = rel.getTurbineGroup();
138 GroupRole groupRole = new BaseJetspeedGroupRole();
139 groupRole.setGroup(group);
140 groupRole.setRole(role);
141 roles.put(group.getName() + role.getName(), groupRole);
142 }
143 }
144 catch(Exception e)
145 {
146 throw new RoleException("Failed to retrieve roles ", e);
147 }
148 return roles.values().iterator();
149 }
150
151 /***
152 * Retrieves all <code>Role</code>s.
153 *
154 * The security service may optionally check the current user context
155 * to determine if the requestor has permission to perform this action.
156 *
157 * @return Iterator over all roles.
158 * @exception RoleException when the security provider has a general failure.
159 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
160 */
161 public Iterator getRoles()
162 throws JetspeedSecurityException
163 {
164 Criteria criteria = new Criteria();
165 List roles;
166 try
167 {
168 roles = TurbineRolePeer.doSelect(criteria);
169 }
170 catch(Exception e)
171 {
172 throw new RoleException("Failed to retrieve roles ", e);
173 }
174 return roles.iterator();
175 }
176
177 /***
178 * Adds a <code>Role</code> into permanent storage.
179 *
180 * The security service may optionally check the current user context
181 * to determine if the requestor has permission to perform this action.
182 *
183 * @exception RoleException when the security provider has a general failure.
184 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
185 */
186 public void addRole(Role role)
187 throws JetspeedSecurityException
188 {
189 if(roleExists(role.getName()))
190 {
191 throw new RoleException("The role '" +
192 role.getName() + "' already exists");
193 }
194
195 try
196 {
197 TurbineRole trole = new TurbineRole();
198 trole.setRoleName(role.getName());
199 Criteria criteria = TurbineRolePeer.buildCriteria(trole);
200 NumberKey key = (NumberKey)TurbineRolePeer.doInsert(criteria);
201 role.setId(key.toString());
202 }
203 catch(Exception e)
204 {
205 throw new RoleException("Failed to create role '" +
206 role.getName() + "'", e);
207 }
208
209 if (cachingEnable)
210 {
211 JetspeedSecurityCache.addRole(role);
212 }
213
214 try
215 {
216 addDefaultRolePSML(role);
217 }
218 catch (Exception e)
219 {
220 try
221 {
222 removeRole(role.getName());
223 }
224 catch (Exception e2)
225 {
226 }
227 throw new RoleException("failed to add default PSML for Role resource", e);
228 }
229
230 }
231
232 protected void addDefaultRolePSML(Role role)
233 throws RoleException
234 {
235 try
236 {
237 JetspeedRunDataService runDataService =
238 (JetspeedRunDataService)TurbineServices.getInstance()
239 .getService(RunDataService.SERVICE_NAME);
240 JetspeedRunData rundata = runDataService.getCurrentRunData();
241 Profile profile = Profiler.createProfile();
242 profile.setRole(role);
243 profile.setMediaType("html");
244 Profiler.createProfile(rundata, profile);
245 }
246 catch (ProfileException e)
247 {
248 try
249 {
250 removeRole(role.getName());
251 }
252 catch(Exception e2)
253 {
254 }
255 throw new RoleException("Failed to create Role PSML", e);
256 }
257 }
258
259 /***
260 * Saves a <code>Role</code> into permanent storage.
261 *
262 * The security service can throw a <code>NotUniqueEntityException</code> when the public
263 * credentials fail to meet the security provider-specific unique constraints.
264 * The security service may optionally check the current user context
265 * to determine if the requestor has permission to perform this action.
266 *
267 * @exception RoleException when the security provider has a general failure.
268 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
269 */
270 public void saveRole(Role role)
271 throws JetspeedSecurityException
272 {
273 if(!roleExists(role.getName()))
274 {
275 throw new RoleException("The role '" +
276 role.getName() + "' doesn't exists");
277 }
278
279 try
280 {
281 if (role instanceof TurbineRole)
282 {
283 TurbineRolePeer.doUpdate((TurbineRole)role);
284 }
285 else
286 {
287 throw new RoleException("TurbineRoleManagment: Role is not a Turbine role, cannot update");
288 }
289
290 }
291 catch(Exception e)
292 {
293 throw new RoleException("Failed to create role '" +
294 role.getName() + "'", e);
295 }
296
297 }
298
299 /***
300 * Removes a <code>Role</code> from the permanent store.
301 *
302 * The security service may optionally check the current user context
303 * to determine if the requestor has permission to perform this action.
304 *
305 * @param rolename the principal identity of the role to be retrieved.
306 * @exception RoleException when the security provider has a general failure.
307 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
308 */
309 public void removeRole(String rolename)
310 throws JetspeedSecurityException
311 {
312 Connection conn = null;
313 try
314 {
315 conn = Torque.getConnection();
316 Role role = this.getRole(rolename);
317
318 Criteria criteria = new Criteria();
319 criteria.add(TurbineRolePeer.ROLE_NAME, rolename);
320
321 if(cascadeDelete)
322 {
323
324 Criteria criteria1 = new Criteria();
325 criteria1.add(TurbineUserGroupRolePeer.ROLE_ID, role.getId());
326 TurbineUserGroupRolePeer.doDelete(criteria1, conn);
327
328 Criteria criteria2 = new Criteria();
329 criteria2.add(TurbineRolePermissionPeer.ROLE_ID, role.getId());
330 TurbineRolePermissionPeer.doDelete(criteria2, conn);
331 }
332
333 TurbineRolePeer.doDelete(criteria, conn);
334 PsmlManager.removeRoleDocuments(role);
335
336 conn.commit();
337
338 if (cachingEnable)
339 {
340 JetspeedSecurityCache.removeAllRoles(rolename);
341 }
342 }
343 catch(Exception e)
344 {
345 try
346 {
347 conn.rollback();
348 }
349 catch (java.sql.SQLException sqle)
350 {
351 Log.error(sqle);
352 }
353 throw new RoleException("Failed to remove role '" +
354 rolename + "'", e);
355 }
356 finally
357 {
358 try
359 {
360 Torque.closeConnection(conn);
361 }
362 catch (Exception e){}
363 }
364
365 }
366
367 /***
368 * Grants a role to a user.
369 *
370 * The security service may optionally check the current user context
371 * to determine if the requestor has permission to perform this action.
372 *
373 * @exception RoleException when the security provider has a general failure retrieving users.
374 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
375 */
376 public void grantRole(String username, String rolename)
377 throws JetspeedSecurityException
378 {
379 grantRole(username, rolename, GroupManagement.DEFAULT_GROUP_NAME);
380 }
381 public void grantRole(String username, String rolename, String groupname)
382 throws JetspeedSecurityException
383 {
384 try
385 {
386 JetspeedUser user = JetspeedSecurity.getUser(username);
387 Role role = this.getRole(rolename);
388 Group group = JetspeedSecurity.getGroup(groupname);
389
390 Criteria criteria = new Criteria();
391 criteria.add(TurbineUserGroupRolePeer.USER_ID, user.getUserId());
392 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, group.getId());
393 criteria.add(TurbineUserGroupRolePeer.ROLE_ID, role.getId());
394 TurbineUserGroupRolePeer.doInsert(criteria);
395
396 if (cachingEnable)
397 {
398 JetspeedSecurityCache.addRole(username, role, group);
399 }
400 }
401 catch(Exception e)
402 {
403 throw new RoleException("Grant role '" + rolename + "' to user '" + username + "' failed: ", e);
404 }
405 }
406
407 /***
408 * Revokes a role from a user.
409 *
410 * The security service may optionally check the current user context
411 * to determine if the requestor has permission to perform this action.
412 *
413 * @exception RoleException when the security provider has a general failure retrieving users.
414 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
415 */
416 public void revokeRole(String username, String rolename)
417 throws JetspeedSecurityException
418 {
419 revokeRole(username, rolename, GroupManagement.DEFAULT_GROUP_NAME);
420 }
421
422 public void revokeRole(String username, String rolename, String groupname)
423 throws JetspeedSecurityException
424 {
425 try
426 {
427 JetspeedUser user = JetspeedSecurity.getUser(username);
428 Role role = this.getRole(rolename);
429 Group group = JetspeedSecurity.getGroup(groupname);
430
431 Criteria criteria = new Criteria();
432 criteria.add(TurbineUserGroupRolePeer.USER_ID, user.getUserId());
433 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, group.getId());
434 criteria.add(TurbineUserGroupRolePeer.ROLE_ID, role.getId());
435 TurbineUserGroupRolePeer.doDelete(criteria);
436
437 if (cachingEnable)
438 {
439 JetspeedSecurityCache.removeRole(username, rolename, groupname);
440 }
441
442 }
443 catch(Exception e)
444 {
445 throw new RoleException("Revoke role '" + rolename + "' to user '" + username + "' failed: ", e);
446 }
447
448 }
449
450 /***
451 * Checks for the relationship of user has a role. Returns true when the user has the given role.
452 *
453 * The security service may optionally check the current user context
454 * to determine if the requestor has permission to perform this action.
455 *
456 * @exception RoleException when the security provider has a general failure retrieving users.
457 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
458 */
459 public boolean hasRole(String username, String rolename)
460 throws JetspeedSecurityException
461 {
462 return hasRole(username, rolename, GroupManagement.DEFAULT_GROUP_NAME);
463 }
464
465 public boolean hasRole(String username, String rolename, String groupname)
466 throws JetspeedSecurityException
467 {
468 List roles;
469
470 try
471 {
472 if (cachingEnable)
473 {
474 CachedAcl acl = JetspeedSecurityCache.getAcl(username);
475 if (null != acl)
476 {
477 return acl.hasRole(rolename, groupname);
478 }
479 }
480 JetspeedUser user = JetspeedSecurity.getUser(username);
481 Role role = this.getRole(rolename);
482 Group group = JetspeedSecurity.getGroup(groupname);
483
484 Criteria criteria = new Criteria();
485 criteria.add(TurbineUserGroupRolePeer.USER_ID, user.getUserId());
486 criteria.add(TurbineUserGroupRolePeer.GROUP_ID, group.getId());
487 criteria.add(TurbineUserGroupRolePeer.ROLE_ID, role.getId());
488 roles = TurbineUserGroupRolePeer.doSelect(criteria);
489
490 }
491 catch(Exception e)
492 {
493 throw new RoleException("Failed to check role '" +
494 rolename + "'", e);
495 }
496 return ( roles.size() > 0 );
497 }
498
499
500 /***
501 * Retrieves a single <code>Role</code> for a given rolename principal.
502 *
503 * The security service may optionally check the current user context
504 * to determine if the requestor has permission to perform this action.
505 *
506 * @param rolename a role principal identity to be retrieved.
507 * @return Role the role record retrieved.
508 * @exception RoleException when the security provider has a general failure.
509 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege
510 */
511 public Role getRole(String rolename)
512 throws JetspeedSecurityException
513 {
514 List roles;
515 try
516 {
517 Criteria criteria = new Criteria();
518 criteria.add(TurbineRolePeer.ROLE_NAME, rolename);
519 roles = TurbineRolePeer.doSelect(criteria);
520 }
521 catch(Exception e)
522 {
523 throw new RoleException("Failed to retrieve role '" +
524 rolename + "'", e);
525 }
526 if ( roles.size() > 1 )
527 {
528 throw new RoleException(
529 "Multiple Roles with same rolename '" + rolename + "'");
530 }
531 if ( roles.size() == 1 )
532 {
533 TurbineRole role = (TurbineRole)roles.get(0);
534 return role;
535 }
536 throw new RoleException("Unknown role '" + rolename + "'");
537
538 }
539
540
541
542
543
544
545 protected JetspeedRunData getRunData()
546 {
547 JetspeedRunData rundata = null;
548 if (this.runDataService != null)
549 {
550 rundata = this.runDataService.getCurrentRunData();
551 }
552 return rundata;
553 }
554
555 /***
556 * Check whether a specified role exists.
557 *
558 * The login name is used for looking up the account.
559 *
560 * @param roleName the name of the role to check for existence.
561 * @return true if the specified account exists
562 * @throws RoleException if there was a general db access error
563 *
564 */
565 protected boolean roleExists(String roleName)
566 throws RoleException
567 {
568 Criteria criteria = new Criteria();
569 criteria.add(TurbineRolePeer.ROLE_NAME, roleName);
570 List roles;
571 try
572 {
573 roles = TurbineRolePeer.doSelect(criteria);
574 }
575 catch(Exception e)
576 {
577 throw new RoleException(
578 "Failed to check account's presence", e);
579 }
580 if (roles.size() < 1)
581 {
582 return false;
583 }
584 return true;
585 }
586
587
588
589
590
591
592 /***
593 * This is the early initialization method called by the
594 * Turbine <code>Service</code> framework
595 * @param conf The <code>ServletConfig</code>
596 * @exception throws a <code>InitializationException</code> if the service
597 * fails to initialize
598 */
599 public synchronized void init(ServletConfig conf)
600 throws InitializationException
601 {
602 if (getInit()) return;
603
604 super.init(conf);
605
606
607 ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
608 .getResources(JetspeedSecurityService.SERVICE_NAME);
609
610 this.runDataService =
611 (JetspeedRunDataService)TurbineServices.getInstance()
612 .getService(RunDataService.SERVICE_NAME);
613
614 cascadeDelete = serviceConf.getBoolean( CASCADE_DELETE, DEFAULT_CASCADE_DELETE );
615 cachingEnable = serviceConf.getBoolean( CACHING_ENABLE, cachingEnable );
616
617 setInit(true);
618 }
619
620
621
622 }
623
624