001/* 002 * Copyright 2016 Anyware Services 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 */ 016package org.ametys.odf.rights; 017 018import java.util.Collections; 019import java.util.HashSet; 020import java.util.List; 021import java.util.Objects; 022import java.util.Set; 023 024import org.apache.avalon.framework.context.Context; 025import org.apache.avalon.framework.context.ContextException; 026import org.apache.avalon.framework.context.Contextualizable; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.components.ContextHelper; 030import org.apache.cocoon.environment.Request; 031 032import org.ametys.cms.content.ContentHelper; 033import org.ametys.cms.content.archive.ArchiveConstants; 034import org.ametys.cms.repository.Content; 035import org.ametys.core.right.AccessController; 036import org.ametys.odf.ODFHelper; 037import org.ametys.odf.ProgramItem; 038import org.ametys.odf.course.Course; 039import org.ametys.odf.courselist.CourseList; 040import org.ametys.odf.coursepart.CoursePart; 041import org.ametys.odf.orgunit.OrgUnit; 042import org.ametys.odf.person.Person; 043import org.ametys.odf.program.AbstractProgram; 044import org.ametys.odf.program.Container; 045import org.ametys.plugins.core.impl.right.AbstractHierarchicalAccessController; 046import org.ametys.plugins.repository.AmetysObject; 047import org.ametys.plugins.repository.AmetysObjectResolver; 048import org.ametys.plugins.repository.RepositoryConstants; 049import org.ametys.plugins.repository.collection.AmetysObjectCollection; 050import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector; 051 052/** 053 * {@link AccessController} for a ODF {@link Content} 054 */ 055public class ODFContentHierarchicalAccessController extends AbstractHierarchicalAccessController<AmetysObject> implements Contextualizable 056{ 057 /** The helper for root content */ 058 protected ODFHelper _odfHelper; 059 /** The helper for contents */ 060 protected ContentHelper _contentHelper; 061 /** The avalon context */ 062 protected Context _context; 063 /** Ametys Object Resolver */ 064 protected AmetysObjectResolver _resolver; 065 066 067 public void contextualize(Context context) throws ContextException 068 { 069 _context = context; 070 } 071 072 @Override 073 public void service(ServiceManager manager) throws ServiceException 074 { 075 super.service(manager); 076 _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE); 077 _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE); 078 _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE); 079 } 080 081 @Override 082 public boolean isSupported(Object object) 083 { 084 return object instanceof ProgramItem || object instanceof OrgUnit || object instanceof Person || object instanceof CoursePart; 085 } 086 087 @Override 088 protected Set<AmetysObject> _getParents(AmetysObject object) 089 { 090 if (!(object instanceof Content)) 091 { 092 return null; 093 } 094 095 Set<AmetysObject> parents = new HashSet<>(); 096 097 if (object instanceof ProgramItem programItem) 098 { 099 parents.addAll(_odfHelper.getParentProgramItems(programItem)); 100 parents.addAll(_getOrgUnits(programItem)); 101 } 102 else if (object instanceof OrgUnit orgUnit) 103 { 104 OrgUnit parentOrgUnit = orgUnit.getParentOrgUnit(); 105 if (parentOrgUnit != null) 106 { 107 parents.add(parentOrgUnit); 108 } 109 } 110 else if (object instanceof CoursePart coursePart) 111 { 112 List<Course> parentCourses = coursePart.getCourses(); 113 if (!parentCourses.isEmpty()) 114 { 115 parents.addAll(parentCourses); 116 } 117 } 118 119 // default 120 AmetysObject parent = object.getParent(); 121 boolean parentAdded = false; 122 if (parent instanceof AmetysObjectCollection collection && (RepositoryConstants.NAMESPACE_PREFIX + ":contents").equals(collection.getName())) 123 { 124 Request request = ContextHelper.getRequest(_context); 125 String originalWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request); 126 if (ArchiveConstants.ARCHIVE_WORKSPACE.equals(originalWorkspace)) 127 { 128 try 129 { 130 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, RepositoryConstants.DEFAULT_WORKSPACE); 131 AmetysObject parentFromDefault = _resolver.resolveByPath(parent.getPath()); 132 parents.add(parentFromDefault); 133 parentAdded = true; 134 } 135 finally 136 { 137 RequestAttributeWorkspaceSelector.setForcedWorkspace(request, originalWorkspace); 138 } 139 } 140 } 141 if (!parentAdded) 142 { 143 parents.add(parent); 144 } 145 146 return parents; 147 } 148 149 private List<OrgUnit> _getOrgUnits(ProgramItem programItem) 150 { 151 Set<String> ouIds = new HashSet<>(); 152 153 if (programItem instanceof AbstractProgram abstractProgram) 154 { 155 ouIds.addAll(abstractProgram.getOrgUnits()); 156 } 157 else if (programItem instanceof Container container) 158 { 159 ouIds.addAll(container.getOrgUnits()); 160 } 161 else if (programItem instanceof CourseList courseList) 162 { 163 List<Course> parentCourses = courseList.getParentCourses(); 164 for (Course parentCourse : parentCourses) 165 { 166 ouIds.addAll(parentCourse.getOrgUnits()); 167 } 168 } 169 else if (programItem instanceof Course course) 170 { 171 ouIds.addAll(course.getOrgUnits()); 172 } 173 174 return ouIds.stream() 175 .filter(Objects::nonNull) 176 .map(_resolver::resolveById) 177 .map(OrgUnit.class::cast) 178 .toList(); 179 } 180 181 @Override 182 protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts) 183 { 184 if (workspacesContexts.contains("/cms")) 185 { 186 return Collections.singleton(_odfHelper.getRootContent()); 187 } 188 return null; 189 } 190}