]> git.aero2k.de Git - tmp/jakarta-migration.git/blob
a8ab08b9cbf91b9511c825dd7306594208a9299c
[tmp/jakarta-migration.git] /
1 /**
2  *  This document is a part of the source code and related artifacts
3  *  for CollectionSpace, an open source collections management system
4  *  for museums and related institutions:
5
6  *  http://www.collectionspace.org
7  *  http://wiki.collectionspace.org
8
9  *  Copyright 2009 University of California at Berkeley
10
11  *  Licensed under the Educational Community License (ECL), Version 2.0.
12  *  You may not use this file except in compliance with this License.
13
14  *  You may obtain a copy of the ECL 2.0 License at
15
16  *  https://source.collectionspace.org/collection-space/LICENSE.txt
17
18  *  Unless required by applicable law or agreed to in writing, software
19  *  distributed under the License is distributed on an "AS IS" BASIS,
20  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
21  *  See the License for the specific language governing permissions and
22  *  limitations under the License.
23  */
24 package org.collectionspace.services.authorization.spring;
25
26 import java.util.ArrayList;
27 import java.util.Iterator;
28 import java.util.List;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31 import org.collectionspace.services.authorization.CSpaceAction;
32 import org.collectionspace.services.authorization.spi.CSpacePermissionManager;
33 import org.collectionspace.services.authorization.CSpaceResource;
34 import org.collectionspace.services.authorization.PermissionException;
35 import org.collectionspace.services.authorization.PermissionNotFoundException;
36 import org.springframework.security.acls.model.AccessControlEntry;
37 import org.springframework.security.acls.model.AclDataAccessException;
38 import org.springframework.security.acls.model.AlreadyExistsException;
39 import org.springframework.security.acls.model.MutableAcl;
40 import org.springframework.security.acls.model.NotFoundException;
41 import org.springframework.security.acls.model.ObjectIdentity;
42 import org.springframework.security.acls.model.Permission;
43 import org.springframework.security.acls.model.Sid;
44 import org.springframework.transaction.TransactionStatus;
45
46 /**
47  * Manages permissions in Spring Security
48  * @author 
49  */
50 public class SpringPermissionManager implements CSpacePermissionManager {
51
52     final Log log = LogFactory.getLog(SpringPermissionManager.class);
53     private SpringAuthorizationProvider provider;
54
55     SpringPermissionManager(SpringAuthorizationProvider provider) {
56         this.provider = provider;
57     }
58
59     /**
60      * addPermissions adds permissions according to the given grant for given
61      * resource#action for each given principal
62      * @param res
63      * @param action
64      * @param principals
65      * @param grant
66      * @throws PermissionException
67      */
68     @Override
69     public void addPermissions(CSpaceResource res, CSpaceAction action, String[] principals, boolean grant)
70             throws PermissionException {
71         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
72         Sid[] sids = SpringAuthorizationProvider.getSids(principals);
73         Permission p = SpringAuthorizationProvider.getPermission(action);
74         TransactionStatus status = provider.beginTransaction("addPermssions");
75
76         //add permission for each sid
77         for (Sid sid : sids) {
78             try {
79                 addPermission(oid, p, sid, grant);
80                 if (log.isDebugEnabled()) {
81                     log.debug("addpermissions(res,action,prin[], grant), success for "
82                             + " res=" + res.toString()
83                             + " action=" + action.toString()
84                             + " grant=" + grant
85                             + " oid=" + oid.toString()
86                             + " perm=" + p.toString()
87                             + " sid=" + sid.toString());
88                 }
89
90             } catch (AlreadyExistsException aex) {
91                 if (log.isWarnEnabled()) {
92                     log.warn("addpermissions(res,action,prin[], grant) failed,"
93                             + " oid=" + oid.toString()
94                             + " res=" + res.toString()
95                             + " grant=" + grant
96                             + " action=" + action.toString()
97                             + " oid=" + oid.toString()
98                             + " perm=" + p.toString(), aex);
99                 }
100                 //keep going
101             } catch (Exception ex) {
102                 String msg = "addpermissions(res,action,prin[], grant) failed,"
103                         + " oid=" + oid.toString()
104                         + " res=" + res.toString()
105                         + " action=" + action.toString()
106                         + " oid=" + oid.toString()
107                         + " perm=" + p.toString()
108                         + " grant=" + grant;
109                 if (log.isDebugEnabled()) {
110                     log.debug(msg, ex);
111                 }
112                 //don't know what might be wrong...stop
113                 provider.rollbackTransaction(status);
114                 if (ex instanceof PermissionException) {
115                     throw (PermissionException) ex;
116                 }
117                 throw new PermissionException(msg, ex);
118             }
119         }//rof
120         provider.commitTransaction(status);
121         if (log.isDebugEnabled()) {
122             log.debug("addpermissions(res,action,prin[], grant), success for "
123                     + " res=" + res.toString()
124                     + " action=" + action.toString()
125                     + " grant=" + grant
126                     + " oid=" + oid.toString()
127                     + " perm=" + p.toString()
128                     + " sids=" + sids.toString());
129         }
130     }
131
132     /**
133      * deletePermissions removes permisions for given resource#action for each given principal
134      * @param res
135      * @param action
136      * @param principals
137      * @throws PermissionNotFoundException
138      * @throws PermissionException
139      */
140     @Override
141     public void deletePermissions(CSpaceResource res, CSpaceAction action, String[] principals)
142             throws PermissionNotFoundException, PermissionException {
143         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
144         Sid[] sids = SpringAuthorizationProvider.getSids(principals);
145         Permission p = SpringAuthorizationProvider.getPermission(action);
146         TransactionStatus status = provider.beginTransaction("deletePermssions");
147         //delete permission for each sid
148         for (Sid sid : sids) {
149             try {
150                 deletePermissions(oid, p, sid);
151                 if (log.isDebugEnabled()) {
152                     log.debug("deletedpermissions(res,action,prin[]), success for "
153                             + " res=" + res.toString()
154                             + " action=" + action.toString()
155                             + " oid=" + oid.toString()
156                             + " perm=" + p.toString()
157                             + " sid=" + sid.toString());
158                 }
159             } catch (AclDataAccessException aex) {
160                 if (log.isWarnEnabled()) {
161                     log.debug("deletepermissions(res,action,prin[]) failed, "
162                             + " oid=" + oid.toString()
163                             + " res=" + res.toString()
164                             + " action=" + action.toString()
165                             + " oid=" + oid.toString()
166                             + " perm=" + p.toString(), aex);
167                 }
168                 //keep going
169             } catch (Exception ex) {
170                 String msg = "deletepermissions(res,action,prin[]) failed,"
171                         + " oid=" + oid.toString()
172                         + " res=" + res.toString()
173                         + " action=" + action.toString()
174                         + " oid=" + oid.toString()
175                         + " perm=" + p.toString();
176                 if (log.isDebugEnabled()) {
177                     log.debug(msg, ex);
178                 }
179                 //don't know what might be wrong...stop
180                 provider.rollbackTransaction(status);
181                 if (ex instanceof PermissionException) {
182                     throw (PermissionException) ex;
183                 }
184                 throw new PermissionException(msg, ex);
185             }
186         }
187         provider.commitTransaction(status);
188         if (log.isDebugEnabled()) {
189             log.debug("deletedpermissions(res,action,prin[]), success for "
190                     + " res=" + res.toString()
191                     + " action=" + action.toString()
192                     + " oid=" + oid.toString()
193                     + " perm=" + p.toString()
194                     + " sids=" + sids.toString());
195         }
196     }
197
198     /**
199      * deletePermissions
200      * @param res
201      * @param action
202      * @throws PermissionNotFoundException
203      * @throws PermissionException
204      */
205     //non-javadoc NOTE: this is a very destructive operation. it would remove all permissions
206     //to access given resource#action for ANY role including administrators
207     @Override
208     public void deletePermissions(CSpaceResource res, CSpaceAction action)
209             throws PermissionNotFoundException, PermissionException {
210         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
211         Permission p = SpringAuthorizationProvider.getPermission(action);
212         TransactionStatus status = provider.beginTransaction("deletePermssions");
213         try {
214             deletePermissions(oid, p, null);
215             provider.commitTransaction(status);
216             if (log.isDebugEnabled()) {
217                 log.debug("deletepermissions(res,action) success, "
218                         + " res=" + res.toString()
219                         + " action=" + action.toString()
220                         + " oid=" + oid.toString()
221                         + " perm=" + p.toString());
222             }
223         } catch (AclDataAccessException aex) {
224             provider.rollbackTransaction(status);
225             log.debug("deletepermissions(res,action) failed,"
226                     + " oid=" + oid.toString()
227                     + " res=" + res.toString()
228                     + " action=" + action.toString()
229                     + " oid=" + oid.toString()
230                     + " perm=" + p.toString(), aex);
231             throw new PermissionException(aex);
232         } catch (Exception ex) {
233             provider.rollbackTransaction(status);
234             String msg = "deletepermissions(res,action,prin[]) failed,"
235                     + " oid=" + oid.toString()
236                     + " res=" + res.toString()
237                     + " action=" + action.toString()
238                     + " oid=" + oid.toString()
239                     + " perm=" + p.toString();
240             if (log.isDebugEnabled()) {
241                 log.debug(msg, ex);
242             }
243             if (ex instanceof PermissionException) {
244                 throw (PermissionException) ex;
245             }
246             throw new PermissionException(msg, ex);
247         }
248
249     }
250
251     /**
252      * deletePermissions
253      * @param res
254      * @throws PermissionNotFoundException
255      * @throws PermissionException
256      */
257     //non-javadoc NOTE: this is a very very destructive operation. it would remove all permissions
258     //to access given resource for ANY action for ANY role including administrators
259     @Override
260     public void deletePermissions(CSpaceResource res)
261             throws PermissionNotFoundException, PermissionException {
262         ObjectIdentity oid = SpringAuthorizationProvider.getObjectIdentity(res);
263         TransactionStatus status = provider.beginTransaction("deletePermssion");
264         try {
265             provider.getProviderAclService().deleteAcl(oid, true);
266             provider.commitTransaction(status);
267             if (log.isDebugEnabled()) {
268                 log.debug("deletepermissions(res) success, "
269                         + " res=" + res.toString()
270                         + " oid=" + oid.toString());
271             }
272         } catch (AclDataAccessException aex) {
273             provider.rollbackTransaction(status);
274             log.debug("deletepermissions(res) failed,"
275                     + " oid=" + oid.toString()
276                     + " res=" + res.toString()
277                     + " oid=" + oid.toString(), aex);
278             throw new PermissionException(aex);
279         } catch (Exception ex) {
280             provider.rollbackTransaction(status);
281             String msg = "deletepermissions(res) failed,"
282                     + " oid=" + oid.toString()
283                     + " res=" + res.toString()
284                     + " oid=" + oid.toString();
285             if (log.isDebugEnabled()) {
286                 log.debug(msg, ex);
287             }
288             if (ex instanceof PermissionException) {
289                 throw (PermissionException) ex;
290             }
291             throw new PermissionException(msg, ex);
292         }
293     }
294
295     /**
296      * addPermission adds permission grant for given object identity for given permission
297      * for given sid
298      * @param oid
299      * @param permission
300      * @param sid
301      * @param grant
302      * @throws PermissionException
303      */
304     private void addPermission(ObjectIdentity oid, Permission permission,
305             Sid sid, boolean grant) throws PermissionException {
306         MutableAcl acl;
307
308         try {
309             acl = getAcl(oid);
310         } catch (NotFoundException nfe) {
311             if (log.isDebugEnabled()) {
312                 log.debug("addPermission: acl not found for oid=" + oid.toString()
313                         + " perm=" + permission.toString()
314                         + " sid=" + sid.toString()
315                         + " grant=" + grant
316                         + " adding...");
317             }
318             acl = provider.getProviderAclService().createAcl(oid);
319         }
320         acl.insertAce(acl.getEntries().size(), permission, sid, grant);
321         provider.getProviderAclService().updateAcl(acl);
322
323         if (log.isDebugEnabled()) {
324             log.debug("addPermission: added acl for oid=" + oid.toString()
325                     + " perm=" + permission.toString()
326                     + " sid=" + sid.toString()
327                     + " grant=" + grant);
328         }
329     }
330
331     /**
332      * deletePermissions deletes given permission on given object id for given sid
333      * @param oid
334      * @param permission
335      * @param sid
336      */
337     //non-javadoc NOTE: if sid is null it would remove ACEs for all sid(s)
338     private void deletePermissions(ObjectIdentity oid, Permission permission, Sid sid) /** throws AclDataAccessException */
339     {
340         int i = 0;
341         MutableAcl acl = getAcl(oid);
342         List<AccessControlEntry> acel = acl.getEntries();
343         int aces = acel.size();
344         if (log.isDebugEnabled()) {
345             log.debug("deletePermissions: for acl oid=" + oid.toString()
346                     + " found " + aces + " aces");
347         }
348         ArrayList<Integer> foundAces = new ArrayList<Integer>();
349         Iterator iter = acel.listIterator();
350         //not possible to delete while iterating
351         while (iter.hasNext()) {
352             AccessControlEntry ace = (AccessControlEntry) iter.next();
353             if (sid != null) {
354                 if (ace.getSid().equals(sid)
355                         && ace.getPermission().equals(permission)) {
356                     foundAces.add(i);
357                 }
358             } else {
359                 if (ace.getPermission().equals(permission)) {
360                     foundAces.add(i);
361                 }
362             }
363             i++;
364         }
365         for (int j = foundAces.size() - 1; j >= 0; j--) {
366             //the following operation does not work while iterating in the while loop
367             acl.deleteAce(foundAces.get(j)); //autobox
368         }
369         provider.getProviderAclService().updateAcl(acl);
370
371         if (log.isDebugEnabled()) {
372             log.debug("deletePermissions: for acl oid=" + oid.toString()
373                     + " deleted " + i + " aces");
374         }
375     }
376
377     private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
378         MutableAcl acl = null;
379         acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
380         if (log.isDebugEnabled()) {
381             log.debug("found acl for oid=" + oid.toString());
382         }
383         return acl;
384     }
385 }