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.Map;
020import java.util.Set;
021
022import org.apache.avalon.framework.service.ServiceException;
023import org.apache.avalon.framework.service.ServiceManager;
024import org.apache.commons.lang3.StringUtils;
025
026import org.ametys.cms.content.ContentHelper;
027import org.ametys.cms.repository.Content;
028import org.ametys.core.right.AccessController;
029import org.ametys.core.right.RightsException;
030import org.ametys.odf.ODFHelper;
031import org.ametys.odf.ProgramItem;
032import org.ametys.odf.coursepart.CoursePart;
033import org.ametys.odf.orgunit.OrgUnit;
034import org.ametys.odf.person.Person;
035import org.ametys.odf.rights.ODFRightHelper.PermissionContext;
036import org.ametys.odf.tree.ODFContentsTreeHelper;
037import org.ametys.plugins.core.impl.right.AbstractHierarchicalWithPermissionContextAccessController;
038import org.ametys.plugins.repository.AmetysObject;
039import org.ametys.plugins.repository.AmetysObjectResolver;
040import org.ametys.plugins.repository.UnknownAmetysObjectException;
041import org.ametys.plugins.repository.collection.AmetysObjectCollection;
042import org.ametys.runtime.i18n.I18nizableText;
043import org.ametys.runtime.i18n.I18nizableTextParameter;
044
045/**
046 * {@link AccessController} for a ODF {@link Content}
047 */
048public class ODFContentHierarchicalAccessController extends AbstractHierarchicalWithPermissionContextAccessController<AmetysObject, ODFRightHelper.PermissionContext>
049{
050    /** the odf context category */
051    public static final I18nizableText ODF_CONTEXT_CATEGORY = new I18nizableText("plugin.odf", "PLUGINS_ODF_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_LABEL");
052    /** The helper for root content */
053    protected ODFHelper _odfHelper;
054    /** The helper for contents */
055    protected ContentHelper _contentHelper;
056    /** Ametys Object Resolver */
057    protected AmetysObjectResolver _resolver;
058    /** The right helper for ODF contents */
059    protected ODFRightHelper _odfRightHelper;
060    /** The ODF contents tree helper */
061    protected ODFContentsTreeHelper _odfContentTreeHelper;
062    
063    @Override
064    public void service(ServiceManager manager) throws ServiceException
065    {
066        super.service(manager);
067        _odfContentTreeHelper = (ODFContentsTreeHelper) manager.lookup(ODFContentsTreeHelper.ROLE);
068        _odfHelper = (ODFHelper) manager.lookup(ODFHelper.ROLE);
069        _odfRightHelper = (ODFRightHelper) manager.lookup(ODFRightHelper.ROLE);
070        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
071        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
072    }
073    
074    public boolean supports(Object object)
075    {
076        return object instanceof ProgramItem || object instanceof OrgUnit || object instanceof Person || object instanceof CoursePart || _isODFRootContent(object);
077    }
078    
079    private boolean _isODFRootContent(Object object)
080    {
081        try
082        {
083            return object.equals(_odfHelper.getRootContent());
084        }
085        catch (UnknownAmetysObjectException e)
086        {
087            // The given object can not be the ODF root content, it does not exist
088            return false;
089        }
090    }
091    
092    @Override
093    protected Set<AmetysObject> _getParents(AmetysObject object, PermissionContext permissionCtx)
094    {
095        if (!(object instanceof Content))
096        {
097            return null;
098        }
099        
100        return _odfRightHelper.getParents((Content) object, permissionCtx);
101    }
102    
103    @Override
104    protected PermissionContext _getPermissionContext(AmetysObject initialObject)
105    {
106        return new PermissionContext((Content) initialObject);
107    }
108    
109    @Override
110    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
111    {
112        if (workspacesContexts.contains("/cms"))
113        {
114            return Collections.singleton(_odfHelper.getRootContent());
115        }
116        return null;
117    }
118    
119    @Override
120    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
121    {
122        if (object instanceof Content)
123        {
124            Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
125            if (object instanceof ProgramItem)
126            {
127                return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_PROGRAM_ITEM_CONTEXT_LABEL", params);
128            }
129            else if (object instanceof CoursePart)
130            {
131                return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_COURSE_PART_CONTEXT_LABEL", params);
132            }
133            else if (object instanceof OrgUnit)
134            {
135                return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_ORGUNIT_CONTEXT_LABEL", params);
136            }
137            else if (object instanceof Person)
138            {
139                return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_PERSON_CONTEXT_LABEL", params);
140            }
141        }
142        else if (object.equals(_odfHelper.getRootContent()))
143        {
144            return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_ROOT_CONTEXT_EXPLANATION_LABEL");
145        }
146        
147        throw new RightsException("Unsupported object " + object.toString());
148    }
149    
150    public I18nizableText getObjectLabel(Object object)
151    {
152        if (object instanceof Content content)
153        {
154            return getContentObjectLabel(content, _odfContentTreeHelper);
155        }
156        else if (object.equals(_odfHelper.getRootContent()))
157        {
158            return new I18nizableText("plugin.odf", "PLUGINS_ODF_ODF_CONTENT_ACCESS_CONTROLLER_ROOT_CONTEXT_LABEL");
159        }
160        throw new RightsException("Unsupported context: " + object.toString());
161    }
162    
163    public I18nizableText getObjectCategory(Object object)
164    {
165        return ODF_CONTEXT_CATEGORY;
166    }
167    
168    public int getObjectPriority(Object object)
169    {
170        if (object instanceof AmetysObjectCollection)
171        {
172            return 10;
173        }
174        return super.getObjectPriority(object);
175    }
176
177    /**
178     * Get a standardized object label for an ODF content
179     * @param content the content
180     * @param helper  the ODF content tree helper
181     * @return the label
182     */
183    public static I18nizableText getContentObjectLabel(Content content, ODFContentsTreeHelper helper)
184    {
185        String code = null;
186        if (content instanceof ProgramItem programItem)
187        {
188            code = programItem.getDisplayCode();
189        }
190        else if (content instanceof OrgUnit orgunit)
191        {
192            code = orgunit.getUAICode();
193        }
194        
195        if (StringUtils.isNotEmpty(code))
196        {
197            return new I18nizableText(content.getTitle() + " [" + code + "]");
198        }
199        else
200        {
201            return new I18nizableText(content.getTitle());
202        }
203    }
204}