001/*
002 *  Copyright 2022 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.plugins.forms.rights;
017
018import java.util.Collections;
019import java.util.Map;
020import java.util.Set;
021
022import org.apache.avalon.framework.context.Context;
023import org.apache.avalon.framework.context.ContextException;
024import org.apache.avalon.framework.context.Contextualizable;
025import org.apache.avalon.framework.service.ServiceException;
026import org.apache.avalon.framework.service.ServiceManager;
027import org.apache.cocoon.components.ContextHelper;
028import org.apache.cocoon.environment.Request;
029import org.apache.commons.lang3.StringUtils;
030
031import org.ametys.core.right.AccessController;
032import org.ametys.core.right.RightsException;
033import org.ametys.plugins.core.impl.right.AbstractHierarchicalAccessController;
034import org.ametys.plugins.forms.dao.FormDirectoryDAO;
035import org.ametys.plugins.forms.repository.Form;
036import org.ametys.plugins.forms.repository.FormDirectory;
037import org.ametys.plugins.forms.repository.FormPage;
038import org.ametys.plugins.forms.repository.FormQuestion;
039import org.ametys.plugins.repository.AmetysObject;
040import org.ametys.runtime.i18n.I18nizableText;
041import org.ametys.runtime.i18n.I18nizableTextParameter;
042import org.ametys.web.WebHelper;
043
044/**
045 * {@link AccessController} for a {@link Form}
046 */
047public class FormAccessController extends AbstractHierarchicalAccessController<AmetysObject> implements Contextualizable
048{
049    /** the form context category */
050    public static final I18nizableText FORM_CONTEXT_CATEGORY = new I18nizableText("plugin.forms", "PLUGINS_FORMS_RIGHTS_CATEGORY");
051    /** The form directory DAO */
052    protected FormDirectoryDAO _formDirectoryDAO;
053    private Context _context;
054    
055    @Override
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        super.service(manager);
059        _formDirectoryDAO = (FormDirectoryDAO) manager.lookup(FormDirectoryDAO.ROLE);
060    }
061    
062    public void contextualize(Context context) throws ContextException
063    {
064        _context = context;
065    }
066    
067    public boolean supports(Object object)
068    {
069        return object instanceof Form || object instanceof FormDirectory || object instanceof FormPage || object instanceof FormQuestion;
070    }
071    
072    @Override
073    protected Set<AmetysObject> _getParents(AmetysObject object)
074    {
075        if (object instanceof FormPage page)
076        {
077            return Set.of(page.getForm());
078        }
079        else if (object instanceof FormQuestion question)
080        {
081            return Set.of(question.getForm());
082        }
083        else if (object instanceof FormDirectory || object instanceof Form)
084        {
085            return Set.of(object.getParent());
086        }
087        
088        return null;
089    }
090    
091    @Override
092    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
093    {
094        Request request = ContextHelper.getRequest(_context);
095        String siteName = WebHelper.getSiteName(request);
096        if (StringUtils.isNotBlank(siteName) && workspacesContexts.contains("/cms"))
097        {
098            return Collections.singleton(_formDirectoryDAO.getFormDirectoriesRootNode(siteName));
099        }
100        return null;
101    }
102    
103    @Override
104    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
105    {
106        if (object instanceof Form)
107        {
108            Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
109            return new I18nizableText("plugin.forms", "PLUGINS_FORMS_ACCESS_CONTROLLER_FORM_CONTEXT_EXPLANATION_LABEL", params);
110        }
111        else if (object instanceof FormDirectory)
112        {
113            Request request = ContextHelper.getRequest(_context);
114            String siteName = WebHelper.getSiteName(request);
115            if (_formDirectoryDAO.getFormDirectoriesRootNode(siteName).equals(object))
116            {
117                return new I18nizableText("plugin.forms", "PLUGINS_FORMS_ACCESS_CONTROLLER_ROOT_CONTEXT_EXPLANATION_LABEL");
118            }
119            else
120            {
121                Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
122                return new I18nizableText("plugin.forms", "PLUGINS_FORMS_ACCESS_CONTROLLER_DIRECTORY_CONTEXT_EXPLANATION_LABEL", params);
123            }
124        }
125        throw new RightsException("Unsupported context " + object.toString());
126    }
127    
128    public I18nizableText getObjectLabel(Object object)
129    {
130        if (object instanceof Form form)
131        {
132            return new I18nizableText(getFormDirectoryPathLabel(form.getParent()) + form.getTitle());
133        }
134        else if (object instanceof FormDirectory directory)
135        {
136            Request request = ContextHelper.getRequest(_context);
137            String siteName = WebHelper.getSiteName(request);
138            if (_formDirectoryDAO.getFormDirectoriesRootNode(siteName).equals(object))
139            {
140                return new I18nizableText("plugin.forms", "PLUGINS_FORMS_ACCESS_CONTROLLER_ROOT_CONTEXT_LABEL");
141            }
142            else
143            {
144                return new I18nizableText(getFormDirectoryPathLabel(directory.getParent()) + directory.getTitle());
145            }
146        }
147        throw new RightsException("Unsupported context " + object.toString());
148    }
149    
150    @Override
151    public I18nizableText getObjectCategory(Object object)
152    {
153        return FORM_CONTEXT_CATEGORY;
154    }
155    
156    @Override
157    public int getObjectPriority(Object object)
158    {
159        if (object instanceof FormDirectory)
160        {
161            Request request = ContextHelper.getRequest(_context);
162            String siteName = WebHelper.getSiteName(request);
163            if (_formDirectoryDAO.getFormDirectoriesRootNode(siteName).equals(object))
164            {
165                return 10;
166            }
167        }
168        return super.getObjectPriority(object);
169    }
170    
171    /**
172     * Get the path as a label for a form directory
173     * If the directory is the root, null is returned instead
174     * @param directory the directory
175     * @return the label
176     */
177    public static String getFormDirectoryPathLabel(FormDirectory directory)
178    {
179        // Do not handle the root directory as any other. We don't want to display it for every Forms
180        if (directory.getParent() instanceof FormDirectory parent)
181        {
182            return getFormDirectoryPathLabel(parent) + directory.getTitle() + " > ";
183        }
184        else
185        {
186            return "";
187        }
188    }
189}