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    public boolean supports(Object object)
069    {
070        return object instanceof SitemapElement;
071    }
072    
073    @Override
074    protected boolean _isSupportedStoredContext(Object storedObject)
075    {
076        if (storedObject instanceof SitemapElement element)
077        {
078            String siteName = WebHelper.getSiteName(ContextHelper.getRequest(_context));
079            return siteName == null
080                    || StringUtils.equals(element.getSiteName(), siteName);
081        }
082        return false;
083    }
084    
085    @Override
086    protected Set<AmetysObject> _getParents(AmetysObject object)
087    {
088        AmetysObject parent = object.getParent();
089        if (supports(parent))
090        {
091            return Collections.singleton(parent);
092        }
093        else
094        {
095            return null;
096        }
097    }
098    
099    @Override
100    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
101    {
102        if (workspacesContexts.contains("/web"))
103        {
104            Request request = ContextHelper.getRequest(_context);
105            
106            String siteName = request.getParameter("siteName");
107            if (siteName == null)
108            {
109                siteName = (String) request.getAttribute("siteName");
110            }
111            if (siteName == null)
112            {
113                siteName = (String) request.getAttribute("site");
114            }
115            
116            if (siteName != null)
117            {
118                Site site = _siteManager.getSite(siteName);
119                if (site != null)
120                {
121                    Set<Sitemap> sitemaps = new HashSet<>();
122                    for (Sitemap sitemap : site.getSitemaps())
123                    {
124                        sitemaps.add(sitemap);
125                    }
126                    return sitemaps;
127                }
128            }
129            
130            getLogger().warn("Could not determine current site to obtain all permissions");
131        }
132        
133        return null;
134    }
135    
136    @Override
137    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
138    {
139        if (object instanceof Page)
140        {
141            Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
142            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_PAGE_CONTEXT_EXPLANATION_LABEL", params);
143        }
144        else if (object instanceof Sitemap sitemap)
145        {
146            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_SITEMAP_CONTEXT_EXPLANATION_LABEL", Map.of("name", new I18nizableText(sitemap.getSitemapName().toUpperCase())));
147        }
148        throw new RightsException("Unsupported object " + object.toString());
149    }
150    
151    @Override
152    public I18nizableText getObjectLabel(Object object) throws RightsException
153    {
154        if (object instanceof Sitemap sitemap)
155        {
156            return new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_ACCESS_CONTROLLER_SITEMAP_CONTEXT_LABEL", Map.of("name", new I18nizableText(sitemap.getSitemapName().toUpperCase())));
157        }
158        else if (object instanceof Page page)
159        {
160            return new I18nizableText(getPageObjectLabel(page));
161        }
162        throw new RightsException("Unsupported object " + object.toString());
163    }
164    
165    public I18nizableText getObjectCategory(Object object)
166    {
167        return PAGE_CONTEXT_CATEGORY;
168    }
169    
170    public int getObjectPriority(Object object)
171    {
172        return object instanceof Sitemap ? 10 : super.getObjectPriority(object);
173    }
174    
175    /**
176     * Get an object label for a page.
177     * 
178     * This label will include the path to the page in the sitemap.
179     * @param page the page
180     * @return the label
181     */
182    public static String getPageObjectLabel(Page page)
183    {
184        SitemapElement parent = page.getParent();
185        if (parent instanceof Sitemap sitemap)
186        {
187            return sitemap.getSitemapName().toUpperCase() + " > " + page.getTitle();
188        }
189        else
190        {
191            return getPageObjectLabel((Page) parent) + " > " + page.getTitle();
192        }
193    }
194}