View Javadoc
1   package org.apache.fulcrum.security.torque.turbine;
2   /*
3    * Licensed to the Apache Software Foundation (ASF) under one
4    * or more contributor license agreements.  See the NOTICE file
5    * distributed with this work for additional information
6    * regarding copyright ownership.  The ASF licenses this file
7    * to you under the Apache License, Version 2.0 (the
8    * "License"); you may not use this file except in compliance
9    * with the License.  You may obtain a copy of the License at
10   *
11   *   http://www.apache.org/licenses/LICENSE-2.0
12   *
13   * Unless required by applicable law or agreed to in writing,
14   * software distributed under the License is distributed on an
15   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16   * KIND, either express or implied.  See the License for the
17   * specific language governing permissions and limitations
18   * under the License.
19   */
20  import java.sql.Connection;
21  
22  import org.apache.fulcrum.security.entity.Group;
23  import org.apache.fulcrum.security.entity.Permission;
24  import org.apache.fulcrum.security.entity.Role;
25  import org.apache.fulcrum.security.entity.User;
26  import org.apache.fulcrum.security.model.turbine.AbstractTurbineModelManager;
27  import org.apache.fulcrum.security.model.turbine.TurbineModelManager;
28  import org.apache.fulcrum.security.model.turbine.entity.TurbineGroup;
29  import org.apache.fulcrum.security.model.turbine.entity.TurbinePermission;
30  import org.apache.fulcrum.security.model.turbine.entity.TurbineRole;
31  import org.apache.fulcrum.security.model.turbine.entity.TurbineUser;
32  import org.apache.fulcrum.security.model.turbine.entity.TurbineUserGroupRole;
33  import org.apache.fulcrum.security.torque.LazyLoadable;
34  import org.apache.fulcrum.security.torque.om.TurbineRolePermissionPeer;
35  import org.apache.fulcrum.security.torque.security.TorqueAbstractSecurityEntity;
36  import org.apache.fulcrum.security.torque.security.turbine.TorqueAbstractTurbineTurbineSecurityEntity;
37  import org.apache.fulcrum.security.util.DataBackendException;
38  import org.apache.fulcrum.security.util.UnknownEntityException;
39  import org.apache.torque.TorqueException;
40  import org.apache.torque.criteria.Criteria;
41  import org.apache.torque.util.Transaction;
42  /**
43   * This implementation persists to a database via Torque.
44   *
45   * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
46   * @version $Id:$
47   */
48  public class TorqueTurbineModelManagerImpl extends AbstractTurbineModelManager implements TurbineModelManager
49  {
50  	/** Serial version */
51  	private static final long serialVersionUID = -306753988209612899L;
52  	
53  
54  	/**
55       * Grants a Role a Permission
56       *
57       * @param role the Role.
58       * @param permission the Permission.
59       * @throws DataBackendException if there was an error accessing the data backend.
60       * @throws UnknownEntityException if role or permission is not present.
61       */
62      @Override
63  	public synchronized void grant(Role role, Permission permission)
64          throws DataBackendException, UnknownEntityException
65      {
66          boolean roleExists = getRoleManager().checkExists(role);
67          boolean permissionExists = getPermissionManager().checkExists(permission);
68  
69          if (roleExists && permissionExists)
70          {
71              if (role instanceof TurbineRole ) {
72              	((TurbineRole)role).addPermission(permission);	
73              }
74              if (permission instanceof TurbinePermission) {
75                  ((TurbinePermission)permission).addRole(role);
76              }
77          
78              Connection con = null;
79  
80              try
81              {
82                  con = Transaction.begin();
83  
84                  ((TorqueAbstractSecurityEntity)role).update(con);
85                  ((TorqueAbstractSecurityEntity)permission).update(con);// this updates all permission
86  
87                  Transaction.commit(con);
88                  con = null;
89              }
90              catch (TorqueException e)
91              {
92                  throw new DataBackendException("grant('" + role.getName() + "', '" + permission.getName() + "') failed", e);
93              }
94              finally
95              {
96                  if (con != null)
97                  {
98                      Transaction.safeRollback(con);
99                  }
100             }
101 
102             return;
103         }
104 
105         if (!roleExists)
106         {
107             throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
108         }
109 
110         if (!permissionExists)
111         {
112             throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
113         }
114     }
115 
116     /**
117      * Revokes a Permission from a Role.
118      *
119      * @param role the Role.
120      * @param permission the Permission.
121      * @throws DataBackendException if there was an error accessing the data backend.
122      * @throws UnknownEntityException if role or permission is not present.
123      */
124     @Override
125 	public synchronized void revoke(Role role, Permission permission)
126         throws DataBackendException, UnknownEntityException
127     {
128         boolean roleExists = getRoleManager().checkExists(role);
129         boolean permissionExists = getPermissionManager().checkExists(permission);
130 
131         if (roleExists && permissionExists)
132         {
133         	if (role instanceof TurbineRole ) {
134         		 ((TurbineRole)role).removePermission(permission);
135             }
136             if (permission instanceof TurbinePermission) {
137             	 ((TurbinePermission)permission).removeRole(role);
138             }
139             
140             try
141             {
142                 Criteria criteria = new Criteria();
143                 criteria.where(TurbineRolePermissionPeer.ROLE_ID, role.getId());
144                 criteria.where(TurbineRolePermissionPeer.PERMISSION_ID, (Integer)permission.getId());
145                 TurbineRolePermissionPeer.doDelete(criteria);
146             }
147             catch (TorqueException e)
148             {
149                 throw new DataBackendException("revoke('" + role.getName() + "', '" + permission.getName() + "') failed", e);
150             }
151 
152             return;
153         }
154 
155         if (!roleExists)
156         {
157             throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
158         }
159 
160         if (!permissionExists)
161         {
162             throw new UnknownEntityException("Unknown permission '" + permission.getName() + "'");
163         }
164     }
165     
166 
167     @Override
168 	public synchronized void grant(User user, Group group, Role role) throws DataBackendException, UnknownEntityException
169     {
170         handlePrivileges(Privilege.GRANT, user, group, role );
171     }
172 
173     @Override
174 	public synchronized void revoke(User user, Group group, Role role)
175         throws DataBackendException, UnknownEntityException
176     {
177         if (checkExists(user, group, role)) 
178             handlePrivileges( Privilege.REVOKE, user, group, role );
179     }
180 
181     @Override
182     public void replace( User user,  Role oldRole, Role newRole )
183         throws DataBackendException, UnknownEntityException
184     {
185         Group group = ((TurbineModelManager)this).getGlobalGroup();
186         if (checkExists(user, oldRole, newRole, group) ) {
187             handlePrivileges( Privilege.REPLACE_ROLE, user, group, oldRole, newRole );
188         }
189     }
190 
191     private void addUserGroupRole( User user, Role role, Group group )
192         throws DataBackendException
193     {
194         TurbineUserGroupRoleTurbineUserGroupRole new_user_group_role = new TurbineUserGroupRole();
195         new_user_group_role.setUser(user);
196         new_user_group_role.setGroup(group);
197         new_user_group_role.setRole(role);
198         ((TurbineUser) user).addUserGroupRole(new_user_group_role);
199         
200         if (group instanceof TurbineGroup ) {
201             if (getGroupManager() instanceof LazyLoadable) {
202                 ((TorqueAbstractTurbineTurbineSecurityEntity) group).addUserGroupRole(new_user_group_role, 
203                                                                                       ((LazyLoadable)getGroupManager()).getLazyLoading());
204             } else {
205                 ((TurbineGroup) group).addUserGroupRole(new_user_group_role);                    
206             }
207         }
208         if (role instanceof TurbineRole ) {
209             if (getRoleManager() instanceof LazyLoadable) {
210                 ((TorqueAbstractTurbineTurbineSecurityEntity) role).addUserGroupRole(new_user_group_role,
211                                                                                      ((LazyLoadable)getRoleManager()).getLazyLoading());
212             } else {
213                 ((TurbineRole) role).addUserGroupRole(new_user_group_role);                    
214             }
215         }
216     }
217 
218     private void removeUserGroupRole( User user, Role role, Group group )
219         throws DataBackendException, UnknownEntityException
220     {
221         boolean ugrFound = false;
222         for (TurbineUserGroupRole user_group_role : ((TurbineUser) user).getUserGroupRoleSet())
223         {
224             if (user_group_role.getUser().equals(user)
225                 && user_group_role.getGroup().equals(group)
226                 && user_group_role.getRole().equals(role))
227             {
228                 ugrFound = true;
229                 ((TurbineUser)user).removeUserGroupRole(user_group_role);
230                 if (group instanceof TurbineGroup ) {
231                     if (getGroupManager() instanceof LazyLoadable) {
232                         ((TorqueAbstractTurbineTurbineSecurityEntity) group).removeUserGroupRole(user_group_role, 
233                                                                                                  ((LazyLoadable)getGroupManager()).getLazyLoading());
234                     } else {
235                         ((TurbineGroup) group).removeUserGroupRole(user_group_role); 
236                     }
237                 }
238                 if (role instanceof TurbineRole ) {
239                     if (getRoleManager() instanceof LazyLoadable) {
240                         ((TorqueAbstractTurbineTurbineSecurityEntity) role).removeUserGroupRole(user_group_role, 
241                                                                                                 ((LazyLoadable)getGroupManager()).getLazyLoading());
242                     } else {
243                         ((TurbineRole) role).removeUserGroupRole(user_group_role);
244                     }
245                 }
246                 break;
247             }
248         }
249         if (!ugrFound)
250         {
251             throw new UnknownEntityException("Could not find User/Group/Role for Role "+ role.getName());
252         }
253     }
254     
255     private boolean checkExists( User user, Group group, Role role ) throws UnknownEntityException, DataBackendException
256     {
257         boolean roleExists = getRoleManager().checkExists(role);
258         boolean userExists = getUserManager().checkExists(user);
259         boolean groupExists = getGroupManager().checkExists(group);
260 
261         if (roleExists && groupExists && userExists)
262         {
263             return true;
264         }
265 
266         if (!roleExists)
267         {
268             throw new UnknownEntityException("Unknown role '" + role.getName() + "'");
269         }
270 
271         if (!groupExists)
272         {
273             throw new UnknownEntityException("Unknown group '" + group.getName() + "'");
274         }
275 
276         if (!userExists)
277         {
278             throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
279         }
280         return false;
281     }
282     
283     private boolean checkExists( User user, Role oldRole, Role newRole, Group globalGroup ) throws UnknownEntityException, DataBackendException
284     {
285         boolean userExists = getUserManager().checkExists(user);
286         boolean oldRoleExists = getRoleManager().checkExists(oldRole);
287         boolean newRoleExists = getRoleManager().checkExists(newRole);
288 
289         if (userExists && oldRoleExists && newRoleExists && globalGroup != null)
290         {
291             return true;
292         }
293 
294         if (!oldRoleExists)
295         {
296             throw new UnknownEntityException("Unknown role '" + oldRole.getName() + "'");
297         }
298         
299         if (!newRoleExists)
300         {
301             throw new UnknownEntityException("Unknown role '" + newRole.getName() + "'");
302         }
303         if (!userExists)
304         {
305             throw new UnknownEntityException("Unknown user '" + user.getName() + "'");
306         }
307         return false;
308     }
309     
310     private void handlePrivileges( Privilege privilege, User user, Group group, Role role, Role newRole )
311                     throws DataBackendException, UnknownEntityException
312     {
313             String logChars = privilege.toString()+ "('"
314                             + user.getName() + "', '"
315                             + group.getName() + "', '"
316                             + role.getName() + "')";
317             switch (privilege) {
318                 case GRANT:
319                     addUserGroupRole( user, role, group );break;
320                 case REVOKE:
321                     removeUserGroupRole( user, role, group );break;
322                 case REPLACE_ROLE:
323                     addUserGroupRole( user, newRole, group );
324                     removeUserGroupRole( user, role, group );
325                     // the user's user-group-role set is updated, i.e. the old one is removed and the new one added -
326                     // no need to do an additional delete in the database
327                     logChars = Privilege.REPLACE_ROLE.toString()+"('"
328                                     + user.getName() + "', '"
329                                     + role.getName() + "', '"
330                                     + newRole.getName() + "')";
331                     break; 
332             }
333             syncPrivilegeWithDatabase( user, logChars );
334     }
335     
336     private void handlePrivileges( Privilege privilege, User user, Group group, Role role )
337                     throws DataBackendException, UnknownEntityException
338     {
339         handlePrivileges( privilege, user, group, role, null );    
340     }
341 
342     private void syncPrivilegeWithDatabase( User user, String logChars)
343         throws DataBackendException
344     {
345         Connection con = null;
346 
347         try
348         {
349             con = Transaction.begin();
350             // save only the new user group may be the better contract, but this would 
351             //  require/add a dependency to initTurbineUserGroupRoles()
352             //((TorqueAbstractSecurityEntity)user).save( con );
353             // update only user
354             ((TorqueAbstractSecurityEntity)user).update(con);
355             //((TorqueAbstractSecurityEntity)group).update(con);
356             //((TorqueAbstractSecurityEntity)role).update(con);
357             Transaction.commit(con);
358             con = null;
359         }
360         catch (TorqueException e)
361         {
362             throw new DataBackendException(logChars +" failed", e);
363         }
364         catch ( Exception e )
365         {
366             throw new DataBackendException(logChars +" failed", e);
367         }
368         finally
369         {
370             if (con != null)
371             {
372                 Transaction.safeRollback(con);
373             }
374         }
375     }
376 }