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