/** * <a href="http://www.openolat.org"> * OpenOLAT - Online Learning and Training</a><br> * <p> * Licensed under the Apache License, Version 2.0 (the "License"); <br> * you may not use this file except in compliance with the License.<br> * You may obtain a copy of the License at the * <a href="http://www.apache.org/licenses/LICENSE-2.0">Apache homepage</a> * <p> * Unless required by applicable law or agreed to in writing,<br> * software distributed under the License is distributed on an "AS IS" BASIS, <br> * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. <br> * See the License for the specific language governing permissions and <br> * limitations under the License. * <p> * Initial code contributed and copyrighted by<br> * frentix GmbH, http://www.frentix.com * <p> */ package org.olat.modules.portfolio; import java.util.Collections; import java.util.List; import org.olat.core.CoreSpringFactory; import org.olat.modules.portfolio.model.AccessRights; import org.olat.repository.model.RepositoryEntrySecurity; /** * * Initial date: 22.06.2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ public class BinderSecurityCallbackFactory { public static final BinderSecurityCallback getCallbackForOwnedBinder(Binder binder) { Binder template = binder.getTemplate(); BinderDeliveryOptions deliveryOptions = getDeliveryOptions(binder); return new BinderSecurityCallbackImpl(true, template != null, deliveryOptions); } public static final BinderSecurityCallback getCallbackForDeletedBinder() { return new BinderSecurityCallbackForDeletedBinder(); } public static final BinderSecurityCallback getCallbackForMyPageList() { return new BinderSecurityCallbackImpl(true, false, null); } /** * The callback for the deleted pages doens't allow anything. * @return */ public static final BinderSecurityCallback getCallbackForDeletedPages() { return new BinderSecurityCallbackForDeletedPages(); } public static final BinderSecurityCallback getReadOnlyCallback() { return new BinderSecurityCallbackImpl(false, false, null); } public static final BinderSecurityCallback getCallbackForTemplate(RepositoryEntrySecurity security) { return new BinderSecurityCallbackForTemplate(security.isEntryAdmin()); } public static final BinderSecurityCallback getCallbackForCoach(Binder binder, List<AccessRights> rights) { Binder template = binder.getTemplate(); BinderDeliveryOptions deliveryOptions = getDeliveryOptions(binder); return new BinderSecurityCallbackImpl(rights, template != null, deliveryOptions); } /** * Invitee can only comment binders * @return */ public static final BinderSecurityCallback getCallbackForInvitation(List<AccessRights> rights) { return new BinderSecurityCallbackForInvitation(rights); } private static final BinderDeliveryOptions getDeliveryOptions(Binder binder) { Binder template = binder.getTemplate(); BinderDeliveryOptions deliveryOptions = null; if(template != null) { deliveryOptions = CoreSpringFactory.getImpl(PortfolioService.class) .getDeliveryOptions(template.getOlatResource()); } return deliveryOptions; } /** * If you can see the business group, you can edit and view the binder. * @return */ public static final BinderSecurityCallback getCallbackForBusinessGroup() { return new BinderSecurityCallbackGroup(true, false, null); } private static class BinderSecurityCallbackForDeletedPages extends DefaultBinderSecurityCallback { @Override public boolean canRestorePage(Page page) { return page.getPageStatus() == PageStatus.deleted; } } private static class BinderSecurityCallbackForDeletedBinder extends DefaultBinderSecurityCallback { @Override public boolean canDeleteBinder(Binder binder) { return true; } @Override public boolean canViewAccessRights(PortfolioElement element) { return true; } @Override public boolean canViewAccessRights() { return true; } @Override public boolean canViewElement(PortfolioElement element) { return true; } @Override public boolean canViewPendingAssignments(Section section) { return true; } @Override public boolean canViewEmptySection(Section section) { return true; } @Override public boolean canViewAssess(PortfolioElement element) { return true; } @Override public boolean canViewAssessment() { return true; } } /** * Can only view / comment the pages, the sections they are allowed * to view or the whole binder. * * Initial date: 20.07.2016<br> * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com * */ private static class BinderSecurityCallbackForInvitation extends DefaultBinderSecurityCallback { private final List<AccessRights> rights; public BinderSecurityCallbackForInvitation(List<AccessRights> rights) { this.rights = rights; } @Override public boolean canComment(PortfolioElement element) { if(element instanceof Page) { Page page = (Page)element; if(page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft) { return false; } } if(rights != null) { for(AccessRights right:rights) { if(right.getRole() == PortfolioRoles.readInvitee && right.matchElementAndAncestors(element)) { return true; } } } return false; } @Override public boolean canViewElement(PortfolioElement element) { if(element instanceof Page) { Page page = (Page)element; if(page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft) { return false; } } if(rights != null) { for(AccessRights right:rights) { if(right.getRole() == PortfolioRoles.readInvitee && right.matchElementAndAncestors(element)) { return true; } } } return false; } } private static class BinderSecurityCallbackForTemplate extends DefaultBinderSecurityCallback { private final boolean admin; public BinderSecurityCallbackForTemplate(boolean admin) { this.admin = admin; } @Override public boolean canEditBinder() { return admin; } @Override public boolean canEditMetadataBinder() { return admin; } @Override public boolean canAddSection() { return admin; } @Override public boolean canEditSection() { return admin; } @Override public boolean canSectionBeginAndEnd() { return true; } @Override public boolean canNewAssignment() { return admin; } @Override public boolean canViewElement(PortfolioElement element) { return true; } @Override public boolean canViewPendingAssignments(Section section) { return true; } } private static class BinderSecurityCallbackGroup extends BinderSecurityCallbackImpl { public BinderSecurityCallbackGroup(boolean owner, boolean task, BinderDeliveryOptions deliveryOptions) { super(owner, task, deliveryOptions); } @Override public boolean canDeleteBinder(Binder binder) { return false; } } private static class BinderSecurityCallbackImpl implements BinderSecurityCallback { /** * The binder is linked to a template. */ private final boolean task; private final boolean owner; private final List<AccessRights> rights; private final BinderDeliveryOptions deliveryOptions; public BinderSecurityCallbackImpl(boolean owner, boolean task, BinderDeliveryOptions deliveryOptions) { this.task = task; this.owner = owner; this.rights = Collections.emptyList(); this.deliveryOptions = deliveryOptions; } public BinderSecurityCallbackImpl(List<AccessRights> rights, boolean task, BinderDeliveryOptions deliveryOptions) { this.owner = false; this.task = task; this.rights = rights; this.deliveryOptions = deliveryOptions; } @Override public boolean canEditBinder() { return owner; } @Override public boolean canMoveToTrashBinder(Binder binder) { if(owner) { if(binder.getBinderStatus() == null || binder.getBinderStatus() == BinderStatus.open) { if(task) { return deliveryOptions.isAllowDeleteBinder(); } else { return true; } } } return false; } @Override public boolean canDeleteBinder(Binder binder) { if(owner) { if(binder.getBinderStatus() == BinderStatus.deleted) { if(task) { return deliveryOptions.isAllowDeleteBinder(); } else { return true; } } } return false; } @Override public boolean canEditMetadataBinder() { return owner && !task; } @Override public boolean canAddSection() { return owner && !task; } @Override public boolean canEditSection() { return owner && !task; } @Override public boolean canCloseSection(Section section) { if(task && rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(section)) { return true; } } } return false; } @Override public boolean canSectionBeginAndEnd() { return false; } @Override public boolean canNewAssignment() { return false; } @Override public boolean canInstantiateAssignment() { return owner; } @Override public boolean canAddPage(Section section) { if(section == null) { return owner && (deliveryOptions == null || deliveryOptions.isAllowNewEntries()); } if(owner) { return section != null && !SectionStatus.isClosed(section) && section.getSectionStatus() != SectionStatus.submitted && (deliveryOptions == null || deliveryOptions.isAllowNewEntries()); } return false; } /** * The owner can only edit the page in task which are in draft or in revision. * Free binder, without task are editable until the page is closed. */ @Override public boolean canEditPage(Page page) { return owner && ( (task && (page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft || page.getPageStatus() == PageStatus.inRevision)) || (!task && !PageStatus.isClosed(page)) ); } @Override public boolean canEditPageMetadata(Page page, List<Assignment> assignments) { if(owner) { if(task) { return assignments == null || assignments.size() == 0; } return true; } return false; } @Override public boolean canPublish(Page page) { return owner && (page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft || page.getPageStatus() == PageStatus.inRevision); } @Override public boolean canRevision(Page page) { if(owner) return false; if(rights != null && page.getPageStatus() == PageStatus.published) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(page)) { return true; } } } return false; } @Override public boolean canDeletePage(Page page) { return owner && page.getPageStatus() != PageStatus.published && page.getPageStatus() != PageStatus.closed && page.getPageStatus() != PageStatus.deleted; } @Override public boolean canRestorePage(Page page) { return owner && page.getPageStatus() == PageStatus.deleted; } @Override public boolean canClose(Page page) { if(owner) { return !task && !PageStatus.isClosed(page); } if(rights != null && (page.getPageStatus() == PageStatus.published || page.getPageStatus() == PageStatus.inRevision)) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(page)) { return true; } } } return false; } @Override public boolean canReopen(Page page) { if(owner) { return !task && PageStatus.isClosed(page); } if(rights != null && PageStatus.isClosed(page)) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(page)) { return true; } } } return false; } @Override public boolean canEditAccessRights(PortfolioElement element) { return owner; } @Override public boolean canViewAccessRights(PortfolioElement element) { if(owner) return true; if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(element)) { return true; } } } return false; } @Override public boolean canViewAccessRights() { if(owner) return true; if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole())) { return true; } } } return false; } @Override public boolean canViewEmptySection(Section section) { if(owner) return true; //need to be recursive, if page -> section too -> binder too??? if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(section)) { return true; } } } return false; } @Override public boolean canViewElement(PortfolioElement element) { if(owner) { return true; } if(element instanceof Page) { Page page = (Page)element; if(page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft) { return owner; } } //need to be recursive, if page -> section too -> binder too??? if(rights != null) { for(AccessRights right:rights) { if((PortfolioRoles.reviewer.equals(right.getRole()) || PortfolioRoles.coach.equals(right.getRole())) && right.matchElementAndAncestors(element)) { return true; } } } return false; } @Override public boolean canViewPendingAssignments(Section section) { if(owner) return true; if(rights != null) { for(AccessRights right:rights) { if((PortfolioRoles.reviewer.equals(right.getRole()) || PortfolioRoles.coach.equals(right.getRole())) && right.matchElementAndAncestors(section)) { return true; } } } return false; } @Override public boolean canComment(PortfolioElement element) { if(element.getType() == PortfolioElementType.page) { Page page = (Page)element; if(page.getPageStatus() == null || page.getPageStatus() == PageStatus.draft) { return false; } } if(owner) return true; if(rights != null) { for(AccessRights right:rights) { if((PortfolioRoles.reviewer.equals(right.getRole()) || PortfolioRoles.coach.equals(right.getRole())) && right.matchElementAndAncestors(element)) { return true; } } } return true; } @Override public boolean canReview(PortfolioElement element) { if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.reviewer.equals(right.getRole()) && right.matchElementAndAncestors(element)) { return true; } } } return false; } @Override public boolean canViewAssess(PortfolioElement element) { if(owner) return true; return canAssess(element); } @Override public boolean canAssess(PortfolioElement element) { if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole()) && right.matchElementAndAncestors(element)) { return true; } } } return false; } @Override public boolean canViewAssessment() { if(owner) { return true; } if(rights != null) { for(AccessRights right:rights) { if(PortfolioRoles.coach.equals(right.getRole())) { return true; } } } return false; } } private static class DefaultBinderSecurityCallback implements BinderSecurityCallback { @Override public boolean canEditBinder() { return false; } @Override public boolean canMoveToTrashBinder(Binder binder) { return false; } @Override public boolean canDeleteBinder(Binder binder) { return false; } @Override public boolean canEditMetadataBinder() { return false; } @Override public boolean canAddSection() { return false; } @Override public boolean canEditSection() { return false; } @Override public boolean canCloseSection(Section section) { return false; } @Override public boolean canSectionBeginAndEnd() { return false; } @Override public boolean canNewAssignment() { return false; } @Override public boolean canInstantiateAssignment() { return false; } @Override public boolean canAddPage(Section section) { return false; } @Override public boolean canEditPage(Page page) { return false; } @Override public boolean canEditPageMetadata(Page page, List<Assignment> assignments) { return false; } @Override public boolean canPublish(Page page) { return false; } @Override public boolean canRevision(Page page) { return false; } @Override public boolean canClose(Page page) { return false; } @Override public boolean canReopen(Page page) { return false; } @Override public boolean canDeletePage(Page page) { return false; } @Override public boolean canRestorePage(Page page) { return false; } @Override public boolean canEditAccessRights(PortfolioElement element) { return false; } @Override public boolean canViewAccessRights(PortfolioElement element) { return false; } @Override public boolean canViewAccessRights() { return false; } @Override public boolean canViewElement(PortfolioElement element) { return false; } @Override public boolean canViewPendingAssignments(Section section) { return false; } @Override public boolean canViewEmptySection(Section section) { return false; } @Override public boolean canComment(PortfolioElement element) { return false; } @Override public boolean canReview(PortfolioElement element) { return false; } @Override public boolean canAssess(PortfolioElement element) { return false; } @Override public boolean canViewAssess(PortfolioElement element) { return false; } @Override public boolean canViewAssessment() { return false; } } }