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 at7 * 8 * http://www.apache.org/licenses/LICENSE-2.09 * 10 * Unless required by applicable law or agreed to in writing, software11 * 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 and14 * limitations under the License.15 */1617packageorg.apache.jetspeed.services.security.turbine;
1819import java.sql.Connection;
20import java.util.HashMap;
21import java.util.Iterator;
22import java.util.List;
2324import javax.servlet.ServletConfig;
2526import org.apache.jetspeed.om.profile.Profile;
27import org.apache.jetspeed.om.profile.ProfileException;
28import org.apache.jetspeed.om.security.Group;
29import org.apache.jetspeed.om.security.JetspeedUser;
30import org.apache.jetspeed.om.security.Role;
31import org.apache.jetspeed.om.security.UserNamePrincipal;
32import org.apache.jetspeed.om.security.turbine.TurbineGroup;
33import org.apache.jetspeed.om.security.turbine.TurbineGroupPeer;
34import org.apache.jetspeed.om.security.turbine.TurbineUserGroupRole;
35import org.apache.jetspeed.om.security.turbine.TurbineUserGroupRolePeer;
36import org.apache.jetspeed.services.JetspeedSecurity;
37import org.apache.jetspeed.services.Profiler;
38import org.apache.jetspeed.services.PsmlManager;
39import org.apache.jetspeed.services.rundata.JetspeedRunData;
40import org.apache.jetspeed.services.rundata.JetspeedRunDataService;
41import org.apache.jetspeed.services.security.GroupException;
42import org.apache.jetspeed.services.security.GroupManagement;
43import org.apache.jetspeed.services.security.JetspeedSecurityException;
44import org.apache.jetspeed.services.security.JetspeedSecurityService;
45import org.apache.torque.Torque;
46import org.apache.torque.om.NumberKey;
47import org.apache.torque.util.Criteria;
48import org.apache.turbine.services.InitializationException;
49import org.apache.turbine.services.TurbineBaseService;
50import org.apache.turbine.services.TurbineServices;
51import org.apache.turbine.services.resources.ResourceService;
52import org.apache.turbine.services.rundata.RunDataService;
53import org.apache.turbine.util.Log;
5455/***56 * Default Jetspeed-Turbine Group Management implementation57 *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 */6263publicclassTurbineGroupManagementextends TurbineBaseService
64 implements GroupManagement65 {
66privateJetspeedRunDataService runDataService = null;
6768privatefinalstatic String CONFIG_DEFAULT_ROLE = "role.default";
69 String defaultRole = "user";
70privatefinalstatic String CASCADE_DELETE = "programmatic.cascade.delete";
71privatefinalstaticboolean DEFAULT_CASCADE_DELETE = true;
72privateboolean cascadeDelete;
7374///////////////////////////////////////////////////////////////////////////75// Group Management Interfaces76///////////////////////////////////////////////////////////////////////////7778/***79 * Retrieves all <code>Group</code>s for a given username principal.80 *81 * The security service may optionally check the current user context82 * 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 privilege88 */89public Iterator getGroups(String username)
90 throws JetspeedSecurityException91 {
92JetspeedUser user = null;
93try94 {
95 user = JetspeedSecurity.getUser(newUserNamePrincipal(username));
96 }
97catch(JetspeedSecurityException e)
98 {
99thrownewGroupException("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;
105106try107 {
108 rels = TurbineUserGroupRolePeer.doSelect(criteria);
109if (rels.size() > 0)
110 {
111 groups = new HashMap(rels.size());
112 }
113else114 groups = new HashMap();
115116for (int ix = 0; ix < rels.size(); ix++)
117 {
118TurbineUserGroupRole rel = (TurbineUserGroupRole)rels.get(ix);
119Group group = rel.getTurbineGroup();
120 groups.put(group.getName(), group);
121 }
122 }
123catch(Exception e)
124 {
125thrownewGroupException("Failed to retrieve groups ", e);
126 }
127return groups.values().iterator();
128 }
129130/***131 * Retrieves all <code>Group</code>s.132 *133 * The security service may optionally check the current user context134 * 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 privilege139 */140public Iterator getGroups()
141 throws JetspeedSecurityException142 {
143 Criteria criteria = new Criteria();
144 List groups;
145try146 {
147 groups = TurbineGroupPeer.doSelect(criteria);
148 }
149catch(Exception e)
150 {
151thrownewGroupException("Failed to retrieve groups ", e);
152 }
153return groups.iterator();
154 }
155156/***157 * Adds a <code>Group</code> into permanent storage.158 *159 * The security service can throw a <code>NotUniqueEntityException</code> when the public160 * credentials fail to meet the security provider-specific unique constraints.161 * The security service may optionally check the current user context162 * 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 meet166 * the security provider-specific unique constraints.167 * @exception InsufficientPrivilegeException when the requestor is denied due to insufficient privilege168 */169publicvoid addGroup(Group group)
170 throws JetspeedSecurityException171 {
172if(groupExists(group.getName()))
173 {
174thrownewGroupException("The group '" +
175 group.getName() + "' already exists");
176 }
177178try179 {
180TurbineGroup tgroup = newTurbineGroup();
181 tgroup.setGroupName(group.getName());
182 Criteria criteria = TurbineGroupPeer.buildCriteria(tgroup);
183 NumberKey key = (NumberKey)TurbineGroupPeer.doInsert(criteria);
184 group.setId(key.toString());
185 }
186catch(Exception e)
187 {
188thrownewGroupException("Failed to create group '" +
189 group.getName() + "'", e);
190 }
191192try193 {
194 addDefaultGroupPSML(group);
195 }
196catch (Exception e)
197 {
198try199 {
200 removeGroup(group.getName());
201 }
202catch (Exception e2)
203 {
204 }
205thrownewGroupException("failed to add default PSML for Group resource", e);
206 }
207208 }
209210protectedvoid addDefaultGroupPSML(Group group)
211 throws GroupException212 {
213try214 {
215JetspeedRunDataService runDataService =
216 (JetspeedRunDataService)TurbineServices.getInstance()
217 .getService(RunDataService.SERVICE_NAME);
218JetspeedRunData rundata = runDataService.getCurrentRunData();
219Profile profile = Profiler.createProfile();
220 profile.setGroup(group);
221 profile.setMediaType("html");
222 Profiler.createProfile(rundata, profile);
223 }
224catch (ProfileException e)
225 {
226try227 {
228 removeGroup(group.getName());
229 }
230catch(Exception e2)
231 {
232 }
233thrownewGroupException("Failed to create Group PSML", e);
234 }
235 }
236237/***238 * Saves a <code>Group</code> into permanent storage.239 *240 * The security service can throw a <code>NotUniqueEntityException</code> when the public241 * credentials fail to meet the security provider-specific unique constraints.242 * The security service may optionally check the current user context243 * 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 privilege247 */248publicvoid saveGroup(Group group)
249 throws JetspeedSecurityException250 {
251if(!groupExists(group.getName()))
252 {
253thrownewGroupException("The group '" +
254 group.getName() + "' doesn't exists");
255 }
256257try258 {
259if (group instanceof TurbineGroup)
260 {
261 TurbineGroupPeer.doUpdate((TurbineGroup)group);
262 }
263else264 {
265thrownewGroupException("TurbineGroupManagment: Group is not a Turbine group, cannot update");
266 }
267268 }
269catch(Exception e)
270 {
271thrownewGroupException("Failed to create group '" +
272 group.getName() + "'", e);
273 }
274275 }
276277/***278 * Removes a <code>Group</code> from the permanent store.279 *280 * The security service may optionally check the current user context281 * 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 privilege286 */287publicvoid removeGroup(String groupname)
288 throws JetspeedSecurityException289 {
290 Connection conn = null;
291try292 {
293 conn = Torque.getConnection();
294Group group = this.getGroup(groupname);
295296 Criteria criteria = new Criteria();
297 criteria.add(TurbineGroupPeer.GROUP_NAME, groupname);
298299if(cascadeDelete)
300 {
301//CASCADE TURBINE_USER_GROUP_ROLE302 Criteria criteria1 = new Criteria();
303 criteria1.add(TurbineUserGroupRolePeer.GROUP_ID, group.getId());
304 TurbineUserGroupRolePeer.doDelete(criteria1, conn);
305 }
306307 TurbineGroupPeer.doDelete(criteria, conn);
308 PsmlManager.removeGroupDocuments(group);
309310 conn.commit();
311312 }
313catch(Exception e)
314 {
315try316 {
317 conn.rollback();
318 }
319catch (java.sql.SQLException sqle)
320 {
321 Log.error(sqle);
322 }
323thrownewGroupException("Failed to remove group '" +
324 groupname + "'", e);
325 }
326finally327 {
328try329 {
330 Torque.closeConnection(conn);
331 }
332catch (Exception e){}
333 }
334335 }
336337/***338 * Join a user to a group.339 *340 * The security service may optionally check the current user context341 * 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 privilege345 */346publicvoid joinGroup(String username, String groupname)
347 throws JetspeedSecurityException348 {
349 joinGroup(username, groupname, defaultRole);
350 }
351352/***353 * Join a user to a group - specific role.354 *355 * The security service may optionally check the current user context356 * 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 privilege360 */361publicvoid joinGroup(String username, String groupname, String rolename)
362 throws JetspeedSecurityException363 {
364try365 {
366JetspeedUser user = JetspeedSecurity.getUser(username);
367Group group = this.getGroup(groupname);
368Role role = JetspeedSecurity.getRole(rolename);
369370 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 }
376catch(Exception e)
377 {
378thrownewGroupException("Join group '" + groupname + "' to user '" + username + "' failed: ", e);
379 }
380 }
381382/***383 * Unjoin a user from a group.384 *385 * The security service may optionally check the current user context386 * 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 privilege390 */391publicvoid unjoinGroup(String username, String groupname)
392 throws JetspeedSecurityException393 {
394 unjoinGroup(username, groupname, defaultRole);
395 }
396397/***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 context401 * 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 privilege405 */406407publicvoid unjoinGroup(String username, String groupname, String rolename)
408 throws JetspeedSecurityException409 {
410try411 {
412JetspeedUser user = JetspeedSecurity.getUser(username);
413Group group = this.getGroup(groupname);
414Role role = JetspeedSecurity.getRole(rolename);
415416 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 }
422catch(Exception e)
423 {
424thrownewGroupException("Unjoin group '" + groupname + "' to user '" + username + "' failed: ", e);
425 }
426 }
427428429/***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 context433 * 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 privilege437 */438publicboolean inGroup(String username, String groupname)
439 throws JetspeedSecurityException440 {
441 List groups;
442443try444 {
445JetspeedUser user = JetspeedSecurity.getUser(username);
446Group group = this.getGroup(groupname);
447448 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);
452453 }
454catch(Exception e)
455 {
456thrownewGroupException("Failed to check group '" +
457 groupname + "'", e);
458 }
459return ( groups.size() > 0 );
460 }
461462/***463 * Retrieves a single <code>Group</code> for a given groupname principal.464 *465 * The security service may optionally check the current user context466 * 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 privilege472 */473publicGroup getGroup(String groupname)
474 throws JetspeedSecurityException475 {
476 List groups;
477try478 {
479 Criteria criteria = new Criteria();
480 criteria.add(TurbineGroupPeer.GROUP_NAME, groupname);
481 groups = TurbineGroupPeer.doSelect(criteria);
482 }
483catch(Exception e)
484 {
485thrownewGroupException("Failed to retrieve group '" +
486 groupname + "'", e);
487 }
488if ( groups.size() > 1 )
489 {
490thrownewGroupException(
491"Multiple Groups with same groupname '" + groupname + "'");
492 }
493if ( groups.size() == 1 )
494 {
495TurbineGroup group = (TurbineGroup)groups.get(0);
496return group;
497 }
498thrownewGroupException("Unknown group '" + groupname + "'");
499500 }
501502///////////////////////////////////////////////////////////////////////////503// Internal504///////////////////////////////////////////////////////////////////////////505506protectedJetspeedRunData getRunData()
507 {
508JetspeedRunData rundata = null;
509if (this.runDataService != null)
510 {
511 rundata = this.runDataService.getCurrentRunData();
512 }
513return rundata;
514 }
515516/***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 exists523 * @throws GroupException if there was a general db access error524 *525 */526protectedboolean groupExists(String groupName)
527 throws GroupException528 {
529 Criteria criteria = new Criteria();
530 criteria.add(TurbineGroupPeer.GROUP_NAME, groupName);
531 List groups;
532try533 {
534 groups = TurbineGroupPeer.doSelect(criteria);
535 }
536catch(Exception e)
537 {
538thrownewGroupException(
539"Failed to check account's presence", e);
540 }
541if (groups.size() < 1)
542 {
543return false;
544 }
545returntrue;
546 }
547548///////////////////////////////////////////////////////////////////////////549// Service Init550///////////////////////////////////////////////////////////////////////////551552553/***554 * This is the early initialization method called by the555 * Turbine <code>Service</code> framework556 * @param conf The <code>ServletConfig</code>557 * @exception throws a <code>InitializationException</code> if the service558 * fails to initialize559 */560publicsynchronizedvoid init(ServletConfig conf)
561 throws InitializationException
562 {
563if (getInit()) return;
564565super.init(conf);
566567// get configuration parameters from Jetspeed Resources568 ResourceService serviceConf = ((TurbineServices)TurbineServices.getInstance())
569 .getResources(JetspeedSecurityService.SERVICE_NAME);
570571this.runDataService =
572 (JetspeedRunDataService)TurbineServices.getInstance()
573 .getService(RunDataService.SERVICE_NAME);
574575 defaultRole = serviceConf.getString(CONFIG_DEFAULT_ROLE, defaultRole);
576 cascadeDelete = serviceConf.getBoolean( CASCADE_DELETE, DEFAULT_CASCADE_DELETE );
577578 setInit(true);
579 }
580 }
581582583