001: /*
002: * Copyright 2004 Outerthought bvba and Schaubroeck nv
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package org.outerj.daisy.repository.serverimpl.acl;
017:
018: import org.outerj.daisy.repository.commonimpl.acl.AclStrategy;
019: import org.outerj.daisy.repository.commonimpl.acl.AclImpl;
020: import org.outerj.daisy.repository.commonimpl.acl.AclEvaluationContext;
021: import org.outerj.daisy.repository.commonimpl.acl.AccessDetailsImpl;
022: import org.outerj.daisy.repository.commonimpl.AuthenticatedUser;
023: import org.outerj.daisy.repository.commonimpl.CommonRepository;
024: import org.outerj.daisy.repository.commonimpl.DocId;
025: import org.outerj.daisy.repository.commonimpl.RepositoryImpl;
026: import org.outerj.daisy.repository.*;
027: import org.outerj.daisy.repository.query.QueryException;
028: import org.outerj.daisy.repository.serverimpl.LocalRepositoryManager;
029: import org.outerj.daisy.jdbcutil.JdbcHelper;
030: import org.outerj.daisy.repository.serverimpl.EventHelper;
031: import org.outerj.daisy.repository.acl.*;
032: import org.outerj.daisy.query.model.PredicateExpr;
033: import org.outerj.daisy.query.model.AclConditionViolation;
034: import org.outerj.daisy.query.model.ExprDocData;
035: import org.outerj.daisy.query.ExtQueryContext;
036: import org.outerj.daisy.query.EvaluationInfo;
037: import org.apache.commons.collections.primitives.ArrayLongList;
038: import org.outerx.daisy.x10.AclUpdatedDocument;
039: import org.outerx.daisy.x10.AclDocument;
040:
041: import java.sql.*;
042: import java.util.*;
043: import java.util.Date;
044: import java.util.concurrent.locks.Lock;
045: import java.util.concurrent.locks.ReentrantLock;
046:
047: /**
048: * Server-side implementation of the AclStrategy interface.
049: *
050: */
051: public class LocalAclStrategy implements AclStrategy,
052: AclEvaluationContext {
053: /**
054: * A lock controlling who (which thread) can read or write ACLs from/to the database.
055: * This is used to serialize all database access (related to ACLs).
056: */
057: private Lock lock = new ReentrantLock();
058: /**
059: * Map containing cached copies of the ACLs which are used for ACL-evaluation.
060: */
061: private final Map<Long, Acl> acls = new HashMap<Long, Acl>();
062: private AuthenticatedUser systemUser;
063: private LocalRepositoryManager.Context context;
064: private JdbcHelper jdbcHelper;
065: private EventHelper eventHelper;
066:
067: public LocalAclStrategy(LocalRepositoryManager.Context context,
068: AuthenticatedUser systemUser, JdbcHelper jdbcHelper) {
069: this .context = context;
070: this .systemUser = systemUser;
071: this .jdbcHelper = jdbcHelper;
072: this .eventHelper = new EventHelper(context, jdbcHelper);
073: }
074:
075: public AclImpl loadAcl(long id, AuthenticatedUser user)
076: throws RepositoryException {
077: try {
078: lock.lockInterruptibly();
079: } catch (InterruptedException e) {
080: throw new RepositoryException("Could not get an ACL lock.",
081: e);
082: }
083: try {
084: return loadAclInternal(id, user);
085: } finally {
086: lock.unlock();
087: }
088: }
089:
090: /**
091: * Loads an ACL, assuming the lock has already been acquired by the caller.
092: */
093: private AclImpl loadAclInternal(long id, AuthenticatedUser user)
094: throws RepositoryException {
095: if (id != 1 && id != 2)
096: throw new RepositoryException("Invalid ACL id: " + id);
097:
098: Connection conn = null;
099: PreparedStatement stmt = null;
100: PreparedStatement stmtEntries = null;
101: PreparedStatement stmtDetails = null;
102: try {
103: conn = context.getDataSource().getConnection();
104: Date lastModified;
105: long lastModifier;
106: long updateCount;
107:
108: stmt = conn
109: .prepareStatement("select last_modified, last_modifier, updatecount from acls where id = ?");
110: stmt.setLong(1, id);
111: ResultSet rs = stmt.executeQuery();
112:
113: if (!rs.next()) {
114: // record for this ACL did not yet exist, make it now
115: stmt.close();
116: lastModified = new Date();
117: lastModifier = systemUser.getId();
118: updateCount = 1;
119: createInitialAclRecord(conn, id, lastModified,
120: lastModifier);
121: } else {
122: lastModified = rs.getTimestamp("last_modified");
123: lastModifier = rs.getLong("last_modifier");
124: updateCount = rs.getLong("updatecount");
125: stmt.close();
126: }
127:
128: AclImpl acl = new AclImpl(this , lastModified, lastModifier,
129: id, user, updateCount);
130:
131: stmtEntries = conn
132: .prepareStatement("select id, subject_user_id, subject_role_id, subject_type, perm_read, perm_write, perm_publish, perm_delete, read_detail from acl_entries where acl_object_id= ? and acl_id = ? order by id");
133: stmtEntries.setLong(2, id);
134: stmtDetails = conn
135: .prepareStatement("select ad_type, ad_data from acl_accessdetail where acl_id = ? and acl_object_id = ? and acl_entry_id = ?");
136: stmtDetails.setLong(1, id);
137: stmt = conn
138: .prepareStatement("select id, objectspec from acl_objects where acl_id = ? order by id");
139: stmt.setLong(1, id);
140: rs = stmt.executeQuery();
141:
142: while (rs.next()) {
143: long objectId = rs.getLong(1);
144: String objectExpr = rs.getString(2);
145: AclObject aclObject = acl.createNewObject(objectExpr);
146:
147: stmtEntries.setLong(1, objectId);
148: ResultSet rsEntries = stmtEntries.executeQuery();
149: while (rsEntries.next()) {
150: AclSubjectType subjectType = subjectTypeFromString(rsEntries
151: .getString("subject_type"));
152: long subjectValue = -1;
153: if (subjectType == AclSubjectType.USER) {
154: subjectValue = rsEntries
155: .getLong("subject_user_id");
156: } else if (subjectType == AclSubjectType.ROLE) {
157: subjectValue = rsEntries
158: .getLong("subject_role_id");
159: }
160: AclEntry aclEntry = aclObject.createNewEntry(
161: subjectType, subjectValue);
162: aclEntry.set(AclPermission.READ,
163: actionTypeFromString(rsEntries
164: .getString("perm_read")));
165: aclEntry.set(AclPermission.WRITE,
166: actionTypeFromString(rsEntries
167: .getString("perm_write")));
168: aclEntry.set(AclPermission.PUBLISH,
169: actionTypeFromString(rsEntries
170: .getString("perm_publish")));
171: aclEntry.set(AclPermission.DELETE,
172: actionTypeFromString(rsEntries
173: .getString("perm_delete")));
174:
175: if (rsEntries.getBoolean("read_detail")) {
176: if (aclEntry.get(AclPermission.READ) != AclActionType.GRANT) {
177: throw new RuntimeException(
178: "Unexpected situation: access details available but read permission not granted.");
179: }
180:
181: long entryId = rsEntries.getLong("id");
182: stmtDetails.setLong(2, objectId);
183: stmtDetails.setLong(3, entryId);
184: ResultSet detailsRs = stmtDetails
185: .executeQuery();
186:
187: AccessDetails details = new AccessDetailsImpl(
188: acl);
189:
190: while (detailsRs.next()) {
191: String type = detailsRs
192: .getString("ad_type");
193: String data = detailsRs
194: .getString("ad_data");
195: if (type.equals("allowfield")) {
196: details.addAccessibleField(data);
197: } else if (type.equals("allowpart")) {
198: details.addAccessiblePart(data);
199: } else {
200: // assume it is a detail permission
201: details.set(AclDetailPermission
202: .fromString(type),
203: AclActionType.fromString(data));
204: }
205: }
206:
207: aclEntry.set(AclPermission.READ,
208: AclActionType.GRANT, details);
209: }
210:
211: aclObject.add(aclEntry);
212: }
213: rsEntries.close();
214:
215: acl.add(aclObject);
216: }
217: return acl;
218: } catch (Throwable e) {
219: throw new RepositoryException("Error loading ACL.", e);
220: } finally {
221: jdbcHelper.closeStatement(stmt);
222: jdbcHelper.closeStatement(stmtEntries);
223: jdbcHelper.closeStatement(stmtDetails);
224: jdbcHelper.closeConnection(conn);
225: }
226: }
227:
228: private void createInitialAclRecord(Connection conn, long id,
229: Date lastModified, long lastModifier) throws SQLException {
230: PreparedStatement stmt = null;
231: try {
232: stmt = conn
233: .prepareStatement("insert into acls(id, name, last_modified, last_modifier, updatecount) values (?,?,?,?,?)");
234: stmt.setLong(1, id);
235: stmt.setString(2, getAclName(id));
236: stmt.setTimestamp(3, new Timestamp(lastModified.getTime()));
237: stmt.setLong(4, lastModifier);
238: stmt.setLong(5, 1L);
239: stmt.execute();
240: } finally {
241: jdbcHelper.closeStatement(stmt);
242: }
243: }
244:
245: private String getAclName(long id) {
246: if (id == 1)
247: return "live";
248: else
249: return "staging";
250: }
251:
252: private AclSubjectType subjectTypeFromString(String subjectType) {
253: if (subjectType.equals("U"))
254: return AclSubjectType.USER;
255: else if (subjectType.equals("R"))
256: return AclSubjectType.ROLE;
257: else if (subjectType.equals("E"))
258: return AclSubjectType.EVERYONE;
259: else
260: throw new RuntimeException(
261: "Got unrecognized subject type string from database: "
262: + subjectType);
263: }
264:
265: private AclActionType actionTypeFromString(String actionType) {
266: if (actionType.equals("G"))
267: return AclActionType.GRANT;
268: else if (actionType.equals("D"))
269: return AclActionType.DENY;
270: else if (actionType.equals("N"))
271: return AclActionType.DO_NOTHING;
272: else
273: throw new RuntimeException(
274: "Got unrecognized action type string from database: "
275: + actionType);
276: }
277:
278: private String stringFromSubjectType(AclSubjectType subjectType) {
279: if (subjectType == AclSubjectType.USER)
280: return "U";
281: else if (subjectType == AclSubjectType.ROLE)
282: return "R";
283: else if (subjectType == AclSubjectType.EVERYONE)
284: return "E";
285: else
286: throw new RuntimeException(
287: "Unrecognized ACL subject type: " + subjectType);
288: }
289:
290: private String stringFromActionType(AclActionType actionType) {
291: if (actionType == AclActionType.DENY)
292: return "D";
293: else if (actionType == AclActionType.GRANT)
294: return "G";
295: else if (actionType == AclActionType.DO_NOTHING)
296: return "N";
297: else
298: throw new RuntimeException("Unrecognized ACL action type: "
299: + actionType);
300: }
301:
302: public void storeAcl(AclImpl acl) throws RepositoryException {
303: if (!acl.getIntimateAccess(this ).getCurrentModifier()
304: .isInAdministratorRole())
305: throw new RepositoryException(
306: "Only the Administrator can store ACLs.");
307:
308: try {
309: lock.lockInterruptibly();
310: } catch (InterruptedException e) {
311: throw new RepositoryException("Could not get an ACL lock.",
312: e);
313: }
314: try {
315: storeAclInternal(acl, false);
316: } finally {
317: lock.unlock();
318: }
319: }
320:
321: /**
322: * Stores an ACL, assuming the lock has already been acquired by the caller.
323: */
324: private void storeAclInternal(AclImpl acl, boolean forceOverwrite)
325: throws RepositoryException {
326: Connection conn = null;
327: PreparedStatement stmt = null;
328: PreparedStatement stmtInsertObject = null;
329: PreparedStatement stmtInsertEntry = null;
330: PreparedStatement stmtInsertDetail = null;
331: ResultSet rs;
332: AclImpl.IntimateAccess aclInt = acl.getIntimateAccess(this );
333: long newUpdateCount;
334: try {
335:
336: Date lastModified = new Date();
337: long lastModifier = aclInt.getCurrentModifier().getId();
338:
339: conn = context.getDataSource().getConnection();
340: jdbcHelper.startTransaction(conn);
341:
342: AclImpl oldAcl = loadAclInternal(aclInt.getId(), aclInt
343: .getCurrentModifier());
344:
345: stmt = conn
346: .prepareStatement("select updatecount from acls where id = ?");
347: stmt.setLong(1, aclInt.getId());
348: rs = stmt.executeQuery();
349:
350: if (!rs.next()) {
351: // Normally you will only be able to save an ACL if you first retrieved it, so at first
352: // it would appear that this situation can't occur, but it can occur via copyStagingToLive
353: createInitialAclRecord(conn, aclInt.getId(),
354: new Date(), systemUser.getId());
355: } else if (!forceOverwrite
356: && acl.getUpdateCount() != rs.getLong(1)) {
357: throw new ConcurrentUpdateException(
358: Acl.class.getName(), String.valueOf(aclInt
359: .getId()));
360: }
361:
362: stmt.close();
363:
364: newUpdateCount = acl.getUpdateCount() + 1;
365:
366: // update lastmodifier/lastmodified information
367: stmt = conn
368: .prepareStatement("update acls set last_modified=?, last_modifier=?, updatecount=? where id=?");
369: stmt.setTimestamp(1, new Timestamp(lastModified.getTime()));
370: stmt.setLong(2, lastModifier);
371: stmt.setLong(3, newUpdateCount);
372: stmt.setLong(4, aclInt.getId());
373: stmt.execute();
374: stmt.close();
375:
376: // drop existing records for this ACL
377: stmt = conn
378: .prepareStatement("delete from acl_objects where acl_id = ?");
379: stmt.setLong(1, aclInt.getId());
380: stmt.execute();
381: stmt.close();
382: stmt = conn
383: .prepareStatement("delete from acl_entries where acl_id = ?");
384: stmt.setLong(1, aclInt.getId());
385: stmt.execute();
386: stmt.close();
387: stmt = conn
388: .prepareStatement("delete from acl_accessdetail where acl_id = ?");
389: stmt.setLong(1, aclInt.getId());
390: stmt.execute();
391: stmt.close();
392:
393: stmtInsertObject = conn
394: .prepareStatement("insert into acl_objects(acl_id, id, objectspec) values(?,?,?)");
395: stmtInsertEntry = conn
396: .prepareStatement("insert into acl_entries(acl_id, acl_object_id, id, subject_user_id, subject_role_id, subject_type, perm_read, perm_write, perm_publish, perm_delete, read_detail) values(?,?,?,?,?,?,?,?,?,?,?)");
397: stmtInsertDetail = conn
398: .prepareStatement("insert into acl_accessdetail(acl_id, acl_object_id, acl_entry_id, ad_type, ad_data) values(?,?,?,?,?)");
399: // insert the new records
400: for (int i = 0; i < acl.size(); i++) {
401: AclObject aclObject = acl.get(i);
402:
403: stmtInsertObject.setLong(1, aclInt.getId());
404: stmtInsertObject.setLong(2, i);
405: stmtInsertObject
406: .setString(3, aclObject.getObjectExpr());
407: stmtInsertObject.execute();
408:
409: for (int j = 0; j < aclObject.size(); j++) {
410: AclEntry aclEntry = aclObject.get(j);
411:
412: stmtInsertEntry.setLong(1, aclInt.getId());
413: stmtInsertEntry.setLong(2, i);
414: stmtInsertEntry.setLong(3, j);
415: if (aclEntry.getSubjectType() == AclSubjectType.USER) {
416: stmtInsertEntry.setLong(4, aclEntry
417: .getSubjectValue());
418: stmtInsertEntry.setNull(5, Types.BIGINT);
419: } else if (aclEntry.getSubjectType() == AclSubjectType.ROLE) {
420: stmtInsertEntry.setNull(4, Types.BIGINT);
421: stmtInsertEntry.setLong(5, aclEntry
422: .getSubjectValue());
423: } else if (aclEntry.getSubjectType() == AclSubjectType.EVERYONE) {
424: stmtInsertEntry.setNull(4, Types.BIGINT);
425: stmtInsertEntry.setNull(5, Types.BIGINT);
426: } else {
427: // This situation should never occur
428: throw new RuntimeException(
429: "Encountered unexpected value for AclSubjectType: "
430: + aclEntry.getSubjectType());
431: }
432: stmtInsertEntry.setString(6,
433: stringFromSubjectType(aclEntry
434: .getSubjectType()));
435: stmtInsertEntry.setString(7,
436: stringFromActionType(aclEntry
437: .get(AclPermission.READ)));
438: stmtInsertEntry.setString(8,
439: stringFromActionType(aclEntry
440: .get(AclPermission.WRITE)));
441: stmtInsertEntry.setString(9,
442: stringFromActionType(aclEntry
443: .get(AclPermission.PUBLISH)));
444: stmtInsertEntry.setString(10,
445: stringFromActionType(aclEntry
446: .get(AclPermission.DELETE)));
447:
448: AccessDetails details = aclEntry
449: .getDetails(AclPermission.READ);
450: stmtInsertEntry.setBoolean(11, details != null);
451: stmtInsertEntry.execute();
452:
453: if (details != null) {
454: stmtInsertDetail.setLong(1, aclInt.getId());
455: stmtInsertDetail.setLong(2, i);
456: stmtInsertDetail.setLong(3, j);
457:
458: for (AclDetailPermission permission : AclDetailPermission
459: .values()) {
460: if (details.get(permission) != AclActionType.DO_NOTHING) {
461: stmtInsertDetail.setString(4,
462: permission.toString());
463: stmtInsertDetail.setString(5, details
464: .get(permission).toString());
465: stmtInsertDetail.execute();
466: }
467: }
468:
469: for (String field : details
470: .getAccessibleFields()) {
471: stmtInsertDetail.setString(4, "allowfield");
472: stmtInsertDetail.setString(5, field);
473: stmtInsertDetail.execute();
474: }
475:
476: for (String part : details.getAccessibleParts()) {
477: stmtInsertDetail.setString(4, "allowpart");
478: stmtInsertDetail.setString(5, part);
479: stmtInsertDetail.execute();
480: }
481: }
482:
483: }
484: }
485:
486: eventHelper.createEvent(createAclUpdatedEvent(oldAcl, acl,
487: lastModified, newUpdateCount), "AclUpdated", conn);
488:
489: conn.commit();
490:
491: // update object state
492: aclInt.setLastModified(lastModified);
493: aclInt.setLastModifier(lastModifier);
494: aclInt.setUpdateCount(acl.getUpdateCount() + 1);
495:
496: // invalidate our cached copy of this ACL.
497: invalidateCachedAcl(aclInt.getId());
498:
499: } catch (Throwable e) {
500: jdbcHelper.rollback(conn);
501: throw new RepositoryException("Error storing ACL.", e);
502: } finally {
503: jdbcHelper.closeStatement(stmt);
504: jdbcHelper.closeStatement(stmtInsertObject);
505: jdbcHelper.closeStatement(stmtInsertEntry);
506: jdbcHelper.closeStatement(stmtInsertDetail);
507: jdbcHelper.closeConnection(conn);
508: }
509:
510: context.getCommonRepository().fireRepositoryEvent(
511: RepositoryEventType.ACL_UPDATED,
512: new Long(aclInt.getId()), newUpdateCount);
513: }
514:
515: private AclUpdatedDocument createAclUpdatedEvent(AclImpl oldAcl,
516: AclImpl newAcl, Date lastModified, long newUpdateCount) {
517: AclUpdatedDocument aclUpdatedDocument = AclUpdatedDocument.Factory
518: .newInstance();
519: AclUpdatedDocument.AclUpdated aclUpdated = aclUpdatedDocument
520: .addNewAclUpdated();
521:
522: aclUpdated.addNewOldAcl().setAcl(oldAcl.getXml().getAcl());
523:
524: AclDocument.Acl newAclXml = newAcl.getXml().getAcl();
525: newAclXml.setLastModified(getCalendar(lastModified));
526: newAclXml.setLastModifier(newAcl.getIntimateAccess(this )
527: .getCurrentModifier().getId());
528: newAclXml.setUpdateCount(newUpdateCount);
529:
530: aclUpdated.addNewNewAcl().setAcl(newAclXml);
531:
532: return aclUpdatedDocument;
533: }
534:
535: private Calendar getCalendar(Date date) {
536: GregorianCalendar calendar = new GregorianCalendar();
537: calendar.setTime(date);
538: return calendar;
539: }
540:
541: private void invalidateCachedAcl(long id) {
542: acls.remove(new Long(id));
543: }
544:
545: private AclImpl getCachedAcl(long id) throws RepositoryException {
546: Long key = new Long(id);
547: AclImpl acl = (AclImpl) acls.get(key);
548: if (acl == null) {
549: synchronized (acls) {
550: // yes, I know double-checking isn't foolproof but that can't cause harm here
551: if (!acls.containsKey(key)) {
552: acl = loadAcl(id, systemUser);
553: acl.makeReadOnly();
554: acls.put(key, acl);
555: } else {
556: acl = (AclImpl) acls.get(key);
557: }
558: }
559: }
560: return acl;
561: }
562:
563: public void copyStagingToLive(AuthenticatedUser user)
564: throws RepositoryException {
565: if (!user.isInAdministratorRole())
566: throw new RepositoryException(
567: "Only Administrators can copy the staging ACL to the live ACL.");
568:
569: try {
570: lock.lockInterruptibly();
571: } catch (InterruptedException e) {
572: throw new RepositoryException("Could not get an ACL lock.",
573: e);
574: }
575: try {
576: AclImpl stagingAcl = loadAclInternal(STAGING_ACL_ID, user);
577: AclImpl liveAcl = loadAclInternal(LIVE_ACL_ID, user);
578: AclImpl.IntimateAccess stagingAclInt = stagingAcl
579: .getIntimateAccess(this );
580: stagingAclInt.setId(LIVE_ACL_ID);
581: stagingAclInt.setUpdateCount(liveAcl.getUpdateCount());
582: storeAclInternal(stagingAcl, true);
583: } finally {
584: lock.unlock();
585: }
586: }
587:
588: public void copyLiveToStaging(AuthenticatedUser user)
589: throws RepositoryException {
590: if (!user.isInAdministratorRole())
591: throw new RepositoryException(
592: "Only Administrators can copy the live ACL to the staging ACL.");
593:
594: try {
595: lock.lockInterruptibly();
596: } catch (InterruptedException e) {
597: throw new RepositoryException("Could not get an ACL lock.",
598: e);
599: }
600: try {
601: AclImpl liveAcl = loadAclInternal(LIVE_ACL_ID, user);
602: AclImpl stagingAcl = loadAclInternal(STAGING_ACL_ID, user);
603: AclImpl.IntimateAccess liveAclInt = liveAcl
604: .getIntimateAccess(this );
605: liveAclInt.setId(STAGING_ACL_ID);
606: liveAclInt.setUpdateCount(stagingAcl.getUpdateCount());
607: storeAclInternal(liveAcl, true);
608: } finally {
609: lock.unlock();
610: }
611: }
612:
613: public Object compileObjectExpression(String expression,
614: Repository repository) throws RepositoryException {
615: try {
616: PredicateExpr expr = context.getQueryFactory()
617: .parsePredicateExpression(expression);
618: expr.prepare(new ExtQueryContext(repository));
619: AclConditionViolation violation = expr.isAclAllowed();
620: if (violation != null)
621: throw new RepositoryException(violation.getMessage());
622: return expr;
623: } catch (QueryException e) {
624: throw new RepositoryException(
625: "Error compiling object selection expression.", e);
626: }
627: }
628:
629: public boolean checkObjectExpression(Object compiledExpression,
630: Document document, Repository repository)
631: throws RepositoryException {
632: try {
633: EvaluationInfo evaluationInfo = new EvaluationInfo(
634: new ExtQueryContext(repository));
635: evaluationInfo.setSearchLastVersion(true);
636: return ((PredicateExpr) compiledExpression).evaluate(
637: new ExprDocData(document, null), evaluationInfo);
638: } catch (QueryException e) {
639: throw new RepositoryException(
640: "Error checking object selection expression.", e);
641: }
642: }
643:
644: public AclResultInfo getAclInfo(AuthenticatedUser user, long id,
645: long userId, long[] roleIds, Document document)
646: throws RepositoryException {
647: if (user.getId() != userId && !user.isInAdministratorRole())
648: throw new RepositoryException(
649: "User "
650: + user.getId()
651: + " is not an Administrator and hence cannot access ACL info of user "
652: + userId);
653:
654: AclImpl acl = getCachedAcl(id);
655: AclEvaluator aclEvaluator = new AclEvaluator(acl, this , this ,
656: new RepositoryImpl(context.getCommonRepository(),
657: systemUser));
658: return aclEvaluator.getAclInfo(userId, roleIds, document);
659: }
660:
661: public AclResultInfo getAclInfo(AuthenticatedUser user, long id,
662: long userId, long[] roleIds, DocId docId, long branchId,
663: long languageId) throws RepositoryException {
664: if (user.getId() != userId && !user.isInAdministratorRole())
665: throw new RepositoryException(
666: "User "
667: + user.getId()
668: + " is not an Administrator and hence cannot access ACL info of user "
669: + userId);
670:
671: Document document = context.getCommonRepository().getDocument(
672: docId, branchId, languageId, false, systemUser);
673: return getAclInfo(user, id, userId, roleIds, document);
674: }
675:
676: public long[] filterDocumentTypes(AuthenticatedUser user,
677: long[] documentTypeIds, long collectionId)
678: throws RepositoryException {
679: AclImpl acl = getCachedAcl(AclStrategy.LIVE_ACL_ID);
680: ArrayLongList result = new ArrayLongList(documentTypeIds.length);
681: AclEvaluator aclEvaluator = new AclEvaluator(acl, this , this ,
682: new RepositoryImpl(context.getCommonRepository(),
683: systemUser));
684:
685: for (long documentTypeId : documentTypeIds) {
686: boolean success = aclEvaluator.hasPotentialWriteAccess(user
687: .getId(), user.getActiveRoleIds(), documentTypeId,
688: collectionId);
689: if (success)
690: result.add(documentTypeId);
691: }
692:
693: return result.toArray();
694: }
695:
696: public VariantKey[] filterDocuments(AuthenticatedUser user,
697: VariantKey[] variantKeys, AclPermission permission,
698: boolean nonLive) throws RepositoryException {
699: AclImpl acl = getCachedAcl(AclStrategy.LIVE_ACL_ID);
700: List<VariantKey> result = new ArrayList<VariantKey>(
701: variantKeys.length);
702: AclEvaluator aclEvaluator = new AclEvaluator(acl, this , this ,
703: new RepositoryImpl(context.getCommonRepository(),
704: systemUser));
705:
706: CommonRepository repository = context.getCommonRepository();
707: for (VariantKey variantKey : variantKeys) {
708: try {
709: Document document = repository.getDocument(variantKey
710: .getDocumentId(), variantKey.getBranchId(),
711: variantKey.getLanguageId(), false, systemUser);
712: AclResultInfo aclResultInfo = aclEvaluator
713: .getAclInfo(user.getId(), user
714: .getActiveRoleIds(), document);
715: if ((nonLive && aclResultInfo
716: .isNonLiveAllowed(permission))
717: || (!nonLive && aclResultInfo
718: .isAllowed(permission)))
719: result.add(variantKey);
720: } catch (DocumentNotFoundException e) {
721: // skip non-existing documents
722: } catch (DocumentVariantNotFoundException e) {
723: // skip non-existing document variants
724: }
725: }
726:
727: return result.toArray(new VariantKey[result.size()]);
728: }
729: }
|