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:
6 * http://www.collectionspace.org
7 * http://wiki.collectionspace.org
9 * Copyright 2009 University of California at Berkeley
11 * Licensed under the Educational Community License (ECL), Version 2.0.
12 * You may not use this file except in compliance with this License.
14 * You may obtain a copy of the ECL 2.0 License at
16 * https://source.collectionspace.org/collection-space/LICENSE.txt
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.
24 package org.collectionspace.services.authorization.spring;
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;
47 * Manages permissions in Spring Security
50 public class SpringPermissionManager implements CSpacePermissionManager {
52 final Log log = LogFactory.getLog(SpringPermissionEvaluator.class);
53 private SpringAuthorizationProvider provider;
55 SpringPermissionManager(SpringAuthorizationProvider provider) {
56 this.provider = provider;
60 public void addPermissions(CSpaceResource res, CSpaceAction action, String[] principals)
61 throws PermissionException {
62 ObjectIdentity oid = SpringAuthorizationProvider.mapResource(res);
63 Sid[] sids = SpringAuthorizationProvider.mapPrincipal(principals);
64 Permission p = SpringAuthorizationProvider.mapPermission(action);
65 TransactionStatus status = provider.beginTransaction("addPermssions");
67 //add permission for each sid
68 for (Sid sid : sids) {
70 addPermission(oid, p, sid);
71 if (log.isDebugEnabled()) {
72 log.debug("addpermissions(res,action,prin[]), success for "
73 + " res=" + res.toString()
74 + " action=" + action.toString()
75 + " oid=" + oid.toString()
76 + " perm=" + p.toString()
77 + " sid=" + sid.toString());
80 } catch (AlreadyExistsException aex) {
81 if (log.isWarnEnabled()) {
82 log.warn("addpermissions(res,action,prin[]) failed,"
83 + " oid=" + oid.toString()
84 + " res=" + res.toString()
85 + " action=" + action.toString()
86 + " oid=" + oid.toString()
87 + " perm=" + p.toString(), aex);
90 } catch (Exception ex) {
91 String msg = "addpermissions(res,action,prin[]) failed,"
92 + " oid=" + oid.toString()
93 + " res=" + res.toString()
94 + " action=" + action.toString()
95 + " oid=" + oid.toString()
96 + " perm=" + p.toString();
97 if (log.isDebugEnabled()) {
100 //don't know what might be wrong...stop
101 provider.rollbackTransaction(status);
102 if (ex instanceof PermissionException) {
103 throw (PermissionException) ex;
105 throw new PermissionException(msg, ex);
108 provider.commitTransaction(status);
109 if (log.isDebugEnabled()) {
110 log.debug("addpermissions(res,action,prin[]), success for "
111 + " res=" + res.toString()
112 + " action=" + action.toString()
113 + " oid=" + oid.toString()
114 + " perm=" + p.toString()
115 + " sids=" + sids.toString());
120 public void deletePermissions(CSpaceResource res, CSpaceAction action, String[] principals)
121 throws PermissionNotFoundException, PermissionException {
122 ObjectIdentity oid = SpringAuthorizationProvider.mapResource(res);
123 Sid[] sids = SpringAuthorizationProvider.mapPrincipal(principals);
124 Permission p = SpringAuthorizationProvider.mapPermission(action);
125 TransactionStatus status = provider.beginTransaction("deletePermssions");
126 //delete permission for each sid
127 for (Sid sid : sids) {
129 deletePermissions(oid, p, sid);
130 if (log.isDebugEnabled()) {
131 log.debug("deletedpermissions(res,action,prin[]), success for "
132 + " res=" + res.toString()
133 + " action=" + action.toString()
134 + " oid=" + oid.toString()
135 + " perm=" + p.toString()
136 + " sid=" + sid.toString());
138 } catch (AclDataAccessException aex) {
139 if (log.isWarnEnabled()) {
140 log.debug("deletepermissions(res,action,prin[]) failed, "
141 + " oid=" + oid.toString()
142 + " res=" + res.toString()
143 + " action=" + action.toString()
144 + " oid=" + oid.toString()
145 + " perm=" + p.toString(), aex);
148 } catch (Exception ex) {
149 String msg = "deletepermissions(res,action,prin[]) failed,"
150 + " oid=" + oid.toString()
151 + " res=" + res.toString()
152 + " action=" + action.toString()
153 + " oid=" + oid.toString()
154 + " perm=" + p.toString();
155 if (log.isDebugEnabled()) {
158 //don't know what might be wrong...stop
159 provider.rollbackTransaction(status);
160 if (ex instanceof PermissionException) {
161 throw (PermissionException) ex;
163 throw new PermissionException(msg, ex);
166 provider.commitTransaction(status);
167 if (log.isDebugEnabled()) {
168 log.debug("deletedpermissions(res,action,prin[]), success for "
169 + " res=" + res.toString()
170 + " action=" + action.toString()
171 + " oid=" + oid.toString()
172 + " perm=" + p.toString()
173 + " sids=" + sids.toString());
178 public void deletePermissions(CSpaceResource res, CSpaceAction action)
179 throws PermissionNotFoundException, PermissionException {
180 ObjectIdentity oid = SpringAuthorizationProvider.mapResource(res);
181 Permission p = SpringAuthorizationProvider.mapPermission(action);
182 TransactionStatus status = provider.beginTransaction("deletePermssions");
184 deletePermissions(oid, p, null);
185 } catch (AclDataAccessException aex) {
186 provider.rollbackTransaction(status);
187 log.debug("deletepermissions(res,action) failed,"
188 + " oid=" + oid.toString()
189 + " res=" + res.toString()
190 + " action=" + action.toString()
191 + " oid=" + oid.toString()
192 + " perm=" + p.toString(), aex);
193 throw new PermissionException(aex);
194 } catch (Exception ex) {
195 provider.rollbackTransaction(status);
196 String msg = "deletepermissions(res,action,prin[]) failed,"
197 + " oid=" + oid.toString()
198 + " res=" + res.toString()
199 + " action=" + action.toString()
200 + " oid=" + oid.toString()
201 + " perm=" + p.toString();
202 if (log.isDebugEnabled()) {
205 if (ex instanceof PermissionException) {
206 throw (PermissionException) ex;
208 throw new PermissionException(msg, ex);
210 provider.commitTransaction(status);
211 if (log.isDebugEnabled()) {
212 log.debug("deletepermissions(res,action) success, "
213 + " res=" + res.toString()
214 + " action=" + action.toString()
215 + " oid=" + oid.toString()
216 + " perm=" + p.toString());
222 public void deletePermissions(CSpaceResource res)
223 throws PermissionNotFoundException, PermissionException {
224 ObjectIdentity oid = SpringAuthorizationProvider.mapResource(res);
225 TransactionStatus status = provider.beginTransaction("addPermssion");
227 provider.getProviderAclService().deleteAcl(oid, true);
228 } catch (AclDataAccessException aex) {
229 provider.rollbackTransaction(status);
230 log.debug("deletepermissions(res) failed,"
231 + " oid=" + oid.toString()
232 + " res=" + res.toString()
233 + " oid=" + oid.toString(), aex);
234 throw new PermissionException(aex);
235 } catch (Exception ex) {
236 provider.rollbackTransaction(status);
237 String msg = "deletepermissions(res) failed,"
238 + " oid=" + oid.toString()
239 + " res=" + res.toString()
240 + " oid=" + oid.toString();
241 if (log.isDebugEnabled()) {
244 if (ex instanceof PermissionException) {
245 throw (PermissionException) ex;
247 throw new PermissionException(msg, ex);
249 provider.commitTransaction(status);
251 if (log.isDebugEnabled()) {
252 log.debug("deletepermissions(res) success, "
253 + " res=" + res.toString()
254 + " oid=" + oid.toString());
258 private void addPermission(ObjectIdentity oid, Permission permission,
259 Sid sid) throws PermissionException {
264 } catch (NotFoundException nfe) {
265 if (log.isDebugEnabled()) {
266 log.debug("addPermission: acl not found for oid=" + oid.toString()
267 + " perm=" + permission.toString()
268 + " sid=" + sid.toString()
271 acl = provider.getProviderAclService().createAcl(oid);
273 acl.insertAce(acl.getEntries().size(), permission, sid, true);
274 provider.getProviderAclService().updateAcl(acl);
276 if (log.isDebugEnabled()) {
277 log.debug("addPermission: added acl for oid=" + oid.toString()
278 + " perm=" + permission.toString()
279 + " sid=" + sid.toString());
283 private void deletePermissions(ObjectIdentity oid, Permission permission, Sid sid) /** throws AclDataAccessException */
286 MutableAcl acl = getAcl(oid);
287 List<AccessControlEntry> acel = acl.getEntries();
288 int aces = acel.size();
289 if (log.isDebugEnabled()) {
290 log.debug("deletePermissions: for acl oid=" + oid.toString()
291 + " found " + aces + " aces");
293 ArrayList<Integer> foundAces = new ArrayList<Integer>();
294 Iterator iter = acel.listIterator();
295 //not possible to delete while iterating
296 while(iter.hasNext()) {
297 AccessControlEntry ace = (AccessControlEntry)iter.next();
299 if (ace.getSid().equals(sid)
300 && ace.getPermission().equals(permission)) {
305 if (ace.getPermission().equals(permission)) {
311 for (int j = foundAces.size() - 1; j >= 0; j--) {
312 //the following operation does not work while iterating in the while loop
313 acl.deleteAce(foundAces.get(j)); //autobox
315 provider.getProviderAclService().updateAcl(acl);
317 if (log.isDebugEnabled()) {
318 log.debug("deletePermissions: for acl oid=" + oid.toString()
319 + " deleted " + i + " aces");
323 private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
324 MutableAcl acl = null;
325 acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
326 if (log.isDebugEnabled()) {
327 log.debug("found acl for oid=" + oid.toString());