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