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.mapAction(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.mapAction(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.mapAction(action);
182 TransactionStatus status = provider.beginTransaction("deletePermssions");
184 deletePermissions(oid, p, null);
185 provider.commitTransaction(status);
186 if (log.isDebugEnabled()) {
187 log.debug("deletepermissions(res,action) success, "
188 + " res=" + res.toString()
189 + " action=" + action.toString()
190 + " oid=" + oid.toString()
191 + " perm=" + p.toString());
193 } catch (AclDataAccessException aex) {
194 provider.rollbackTransaction(status);
195 log.debug("deletepermissions(res,action) failed,"
196 + " oid=" + oid.toString()
197 + " res=" + res.toString()
198 + " action=" + action.toString()
199 + " oid=" + oid.toString()
200 + " perm=" + p.toString(), aex);
201 throw new PermissionException(aex);
202 } catch (Exception ex) {
203 provider.rollbackTransaction(status);
204 String msg = "deletepermissions(res,action,prin[]) failed,"
205 + " oid=" + oid.toString()
206 + " res=" + res.toString()
207 + " action=" + action.toString()
208 + " oid=" + oid.toString()
209 + " perm=" + p.toString();
210 if (log.isDebugEnabled()) {
213 if (ex instanceof PermissionException) {
214 throw (PermissionException) ex;
216 throw new PermissionException(msg, ex);
222 public void deletePermissions(CSpaceResource res)
223 throws PermissionNotFoundException, PermissionException {
224 ObjectIdentity oid = SpringAuthorizationProvider.mapResource(res);
225 TransactionStatus status = provider.beginTransaction("deletePermssion");
227 provider.getProviderAclService().deleteAcl(oid, true);
228 provider.commitTransaction(status);
229 if (log.isDebugEnabled()) {
230 log.debug("deletepermissions(res) success, "
231 + " res=" + res.toString()
232 + " oid=" + oid.toString());
234 } catch (AclDataAccessException aex) {
235 provider.rollbackTransaction(status);
236 log.debug("deletepermissions(res) failed,"
237 + " oid=" + oid.toString()
238 + " res=" + res.toString()
239 + " oid=" + oid.toString(), aex);
240 throw new PermissionException(aex);
241 } catch (Exception ex) {
242 provider.rollbackTransaction(status);
243 String msg = "deletepermissions(res) failed,"
244 + " oid=" + oid.toString()
245 + " res=" + res.toString()
246 + " oid=" + oid.toString();
247 if (log.isDebugEnabled()) {
250 if (ex instanceof PermissionException) {
251 throw (PermissionException) ex;
253 throw new PermissionException(msg, ex);
257 private void addPermission(ObjectIdentity oid, Permission permission,
258 Sid sid) throws PermissionException {
263 } catch (NotFoundException nfe) {
264 if (log.isDebugEnabled()) {
265 log.debug("addPermission: acl not found for oid=" + oid.toString()
266 + " perm=" + permission.toString()
267 + " sid=" + sid.toString()
270 acl = provider.getProviderAclService().createAcl(oid);
272 acl.insertAce(acl.getEntries().size(), permission, sid, true);
273 provider.getProviderAclService().updateAcl(acl);
275 if (log.isDebugEnabled()) {
276 log.debug("addPermission: added acl for oid=" + oid.toString()
277 + " perm=" + permission.toString()
278 + " sid=" + sid.toString());
282 private void deletePermissions(ObjectIdentity oid, Permission permission, Sid sid) /** throws AclDataAccessException */
285 MutableAcl acl = getAcl(oid);
286 List<AccessControlEntry> acel = acl.getEntries();
287 int aces = acel.size();
288 if (log.isDebugEnabled()) {
289 log.debug("deletePermissions: for acl oid=" + oid.toString()
290 + " found " + aces + " aces");
292 ArrayList<Integer> foundAces = new ArrayList<Integer>();
293 Iterator iter = acel.listIterator();
294 //not possible to delete while iterating
295 while (iter.hasNext()) {
296 AccessControlEntry ace = (AccessControlEntry) iter.next();
298 if (ace.getSid().equals(sid)
299 && ace.getPermission().equals(permission)) {
304 if (ace.getPermission().equals(permission)) {
310 for (int j = foundAces.size() - 1; j >= 0; j--) {
311 //the following operation does not work while iterating in the while loop
312 acl.deleteAce(foundAces.get(j)); //autobox
314 provider.getProviderAclService().updateAcl(acl);
316 if (log.isDebugEnabled()) {
317 log.debug("deletePermissions: for acl oid=" + oid.toString()
318 + " deleted " + i + " aces");
322 private MutableAcl getAcl(ObjectIdentity oid) throws NotFoundException {
323 MutableAcl acl = null;
324 acl = (MutableAcl) provider.getProviderAclService().readAclById(oid);
325 if (log.isDebugEnabled()) {
326 log.debug("found acl for oid=" + oid.toString());