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.web.rights;
017
018import java.util.Collections;
019import java.util.HashSet;
020import java.util.Map;
021import java.util.Set;
022
023import org.apache.avalon.framework.context.Context;
024import org.apache.avalon.framework.context.ContextException;
025import org.apache.avalon.framework.context.Contextualizable;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.cocoon.components.ContextHelper;
029import org.apache.cocoon.environment.Request;
030import org.apache.commons.codec.binary.StringUtils;
031
032import org.ametys.core.right.AccessController;
033import org.ametys.core.right.RightsException;
034import org.ametys.plugins.core.impl.right.AbstractHierarchicalAccessController;
035import org.ametys.plugins.repository.AmetysObject;
036import org.ametys.runtime.i18n.I18nizableText;
037import org.ametys.runtime.i18n.I18nizableTextParameter;
038import org.ametys.web.WebHelper;
039import org.ametys.web.repository.page.Page;
040import org.ametys.web.repository.page.SitemapElement;
041import org.ametys.web.repository.site.Site;
042import org.ametys.web.repository.site.SiteManager;
043import org.ametys.web.repository.sitemap.Sitemap;
044
045/**
046 * {@link AccessController} for a {@link Page}
047 */
048public class PageAccessController extends AbstractHierarchicalAccessController<AmetysObject> implements Contextualizable
049{
050    /** the page context category */
051    public static final I18nizableText PAGE_CONTEXT_CATEGORY = new I18nizableText("plugin.web", "PLUGINS_WEB_RIGHT_ASSIGNMENT_CONTEXT_PAGES_LABEL");
052    /** The web site manager */
053    protected SiteManager _siteManager;
054    private Context _context;
055    
056    @Override
057    public void service(ServiceManager manager) throws ServiceException
058    {
059        super.service(manager);
060        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
061    }
062    
063    public void contextualize(Context context) throws ContextException
064    {
065        _context = context;
066    }
067    
068    @Override
069    public boolean isSupported(Object object)
070    {
071        return object instanceof SitemapElement;
072    }
073    
074    @Override
075    protected boolean _isSupportedStoredContext(Object storedObject)
076    {
077        if (storedObject instanceof SitemapElement element)
078        {
079            String siteName = WebHelper.getSiteName(ContextHelper.getRequest(_context));
080            return siteName == null
081                    || StringUtils.equals(element.getSiteName(), siteName);
082        }
083        return false;
084    }
085    
086    @Override
087    protected Set<AmetysObject> _getParents(AmetysObject object)
088    {
089        AmetysObject parent = object.getParent();
090        if (isSupported(parent))
091        {
092            return Collections.singleton(parent);
093        }
094        else
095        {
096            return null;
097        }
098    }
099    
100    @Override
101    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
102    {
103        if (workspacesContexts.contains("/web"))
104        {
105            Request request = ContextHelper.getRequest(_context);
106            
107            String siteName = request.getParameter("siteName");
108            if (siteName == null)
109            {
110                siteName = (String) request.getAttribute("siteName");
111            }
112            if (siteName == null)
113            {
114                siteName = (String) request.getAttribute("site");
115            }
116            
117            if (siteName != null)
118            {
119                Site site = _siteManager.getSite(siteName);
120                if (site != null)
121                {
122                    Set<Sitemap> sitemaps = new HashSet<>();
123                    for (Sitemap sitemap : site.getSitemaps())
124                    {
125                        sitemaps.add(sitemap);
126                    }
127                    return sitemaps;
128                }
129            }
130            
131            getLogger().warn("Could not determine current site to obtain all permissions");
132        }
133        
134        return null;
135    }
136    
137    @Override
138    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
139    {
140        if (object instanceof Page)
141        {
142            Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
143            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_PAGE_CONTEXT_EXPLANATION_LABEL", params);
144        }
145        else if (object instanceof Sitemap sitemap)
146        {
147            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_SITEMAP_CONTEXT_EXPLANATION_LABEL", Map.of("name", new I18nizableText(sitemap.getSitemapName().toUpperCase())));
148        }
149        throw new RightsException("Unsupported object " + object.toString());
150    }
151    
152    @Override
153    public I18nizableText getObjectLabel(Object object) throws RightsException
154    {
155        if (object instanceof Sitemap sitemap)
156        {
157            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_SITEMAP_CONTEXT_LABEL", Map.of("name", new I18nizableText(sitemap.getSitemapName().toUpperCase())));
158        }
159        else if (object instanceof Page page)
160        {
161            return new I18nizableText(getPageObjectLabel(page));
162        }
163        throw new RightsException("Unsupported object " + object.toString());
164    }
165    
166    public I18nizableText getObjectCategory(Object object)
167    {
168        return PAGE_CONTEXT_CATEGORY;
169    }
170    
171    public int getObjectPriority(Object object)
172    {
173        return object instanceof Sitemap ? 10 : super.getObjectPriority(object);
174    }
175    
176    /**
177     * Get an object label for a page.
178     * 
179     * This label will include the path to the page in the sitemap.
180     * @param page the page
181     * @return the label
182     */
183    public static String getPageObjectLabel(Page page)
184    {
185        SitemapElement parent = page.getParent();
186        if (parent instanceof Sitemap sitemap)
187        {
188            return sitemap.getSitemapName().toUpperCase() + " > " + page.getTitle();
189        }
190        else
191        {
192            return getPageObjectLabel((Page) parent) + " > " + page.getTitle();
193        }
194    }
195}