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.cms.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;
029
030import org.ametys.cms.content.ContentHelper;
031import org.ametys.cms.content.RootContentHelper;
032import org.ametys.cms.content.archive.ArchiveConstants;
033import org.ametys.cms.repository.Content;
034import org.ametys.core.right.AccessController;
035import org.ametys.core.right.RightsException;
036import org.ametys.plugins.core.impl.right.AbstractHierarchicalAccessController;
037import org.ametys.plugins.repository.AmetysObject;
038import org.ametys.plugins.repository.AmetysObjectResolver;
039import org.ametys.plugins.repository.AmetysRepositoryException;
040import org.ametys.plugins.repository.RepositoryConstants;
041import org.ametys.plugins.repository.collection.AmetysObjectCollection;
042import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector;
043import org.ametys.runtime.i18n.I18nizableText;
044
045/**
046 * {@link AccessController} for a {@link Content}
047 */
048public class ContentAccessController extends AbstractHierarchicalAccessController<AmetysObject> implements Contextualizable
049{
050    /** The content context category */
051    public static final I18nizableText CONTENT_CONTEXT_CATEGORY = new I18nizableText("plugin.cms", "PLUGINS_CMS_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_LABEL");
052    
053    /** The helper for root content */
054    protected RootContentHelper _rootContentHelper;
055    /** The helper for contents */
056    protected ContentHelper _contentHelper;
057    /** Ametys Object Resolver */
058    protected AmetysObjectResolver _resolver;
059    /** The avalon context */
060    protected Context _context;
061    
062    @Override
063    public void service(ServiceManager manager) throws ServiceException
064    {
065        super.service(manager);
066        _rootContentHelper = (RootContentHelper) manager.lookup(RootContentHelper.ROLE);
067        _contentHelper = (ContentHelper) manager.lookup(ContentHelper.ROLE);
068        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
069    }
070    
071    public void contextualize(Context context) throws ContextException
072    {
073        _context = context;
074    }
075    
076    @Override
077    public boolean isSupported(Object object)
078    {
079        try
080        {
081            return object instanceof Content && _rootContentHelper.isChildOfRootContent((Content) object)
082                   || object != null && object.equals(_rootContentHelper.getRootContent());
083        }
084        catch (AmetysRepositoryException e)
085        {
086            getLogger().info("The contents root cannot be retrieved.", e);
087            return false;
088        }
089    }
090    
091    @Override
092    protected Set<AmetysObject> _getParents(AmetysObject object)
093    {
094        if (object instanceof Content)
095        {
096            AmetysObject parent = object.getParent();
097            if (parent instanceof AmetysObjectCollection && (RepositoryConstants.NAMESPACE_PREFIX_INTERNAL + ":contents").equals(((AmetysObjectCollection) parent).getName()))
098            {
099                Request request = ContextHelper.getRequest(_context);
100                String originalWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request);
101                if (ArchiveConstants.ARCHIVE_WORKSPACE.equals(originalWorkspace))
102                {
103                    try
104                    {
105                        RequestAttributeWorkspaceSelector.setForcedWorkspace(request, RepositoryConstants.DEFAULT_WORKSPACE);
106                        AmetysObject parentFromDefault = _resolver.resolveByPath(parent.getPath());
107                        return Collections.singleton(parentFromDefault);
108                        
109                    }
110                    finally
111                    {
112                        RequestAttributeWorkspaceSelector.setForcedWorkspace(request, originalWorkspace);
113                    }
114                }
115            }
116            
117            return Collections.singleton(parent);
118        }
119        else
120        {
121            return null;
122        }
123    }
124    
125    @Override
126    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
127    {
128        if (workspacesContexts.contains("/cms"))
129        {
130            return Collections.singleton(_rootContentHelper.getRootContent());
131        }
132        return null;
133    }
134    
135    @Override
136    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
137    {
138        if (object instanceof Content)
139        {
140            return new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_ACCESS_CONTROLLER_CONTENT_CONTEXT_EXPLANATION_LABEL",
141                    Map.of("title", getObjectLabel(object)));
142        }
143        else if (object instanceof AmetysObjectCollection)
144        {
145            return new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_ACCESS_CONTROLLER_CONTENT_CONTEXT_EXPLANATION_LABEL");
146        }
147        throw new RightsException("Unsupported context " + object.toString());
148    }
149    
150    @Override
151    public I18nizableText getObjectLabel(Object object) throws RightsException
152    {
153        if (object instanceof Content content)
154        {
155            return new I18nizableText(content.getTitle());
156        }
157        else if (object instanceof AmetysObjectCollection)
158        {
159            return new I18nizableText("plugin.cms", "PLUGINS_CMS_CONTENT_ACCESS_CONTROLLER_ROOT_CONTEXT_LABEL");
160        }
161        throw new RightsException("Unsupported context " + object.toString());
162    }
163    
164    public I18nizableText getObjectCategory(Object object)
165    {
166        return CONTENT_CONTEXT_CATEGORY;
167    }
168    
169    public int getObjectPriority(Object object)
170    {
171        if (object instanceof AmetysObjectCollection)
172        {
173            return 10;
174        }
175        return super.getObjectPriority(object);
176    }
177}