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