View Javadoc

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