001/*
002 *  Copyright 2017 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.userdirectory.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;
030
031import org.ametys.cms.contenttype.ContentTypesHelper;
032import org.ametys.cms.repository.Content;
033import org.ametys.core.right.AccessController;
034import org.ametys.core.right.RightsException;
035import org.ametys.plugins.core.impl.right.AbstractHierarchicalAccessController;
036import org.ametys.plugins.repository.AmetysObject;
037import org.ametys.plugins.repository.AmetysObjectResolver;
038import org.ametys.plugins.repository.RepositoryConstants;
039import org.ametys.plugins.repository.UnknownAmetysObjectException;
040import org.ametys.plugins.repository.provider.RequestAttributeWorkspaceSelector;
041import org.ametys.plugins.userdirectory.OrganisationChartPageHandler;
042import org.ametys.plugins.userdirectory.UserDirectoryHelper;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.runtime.i18n.I18nizableTextParameter;
045
046/**
047 * {@link AccessController} for a User directory {@link Content}
048 */
049public class UserDirectoryContentAccessController extends AbstractHierarchicalAccessController<AmetysObject> implements Contextualizable
050{
051    /** the user directory context category */
052    public static final I18nizableText USER_DIRECTORY_CONTEXT_CATEGORY = new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_RIGHT_ASSIGNMENT_CONTEXT_CONTENTS_LABEL");
053
054    /** Ametys Object Resolver */
055    protected AmetysObjectResolver _resolver;
056    
057    /** The organisation chart page handler */
058    protected OrganisationChartPageHandler _organisationChartPageHandler;
059    
060    /** The content type helper */
061    protected ContentTypesHelper _contentTypeHelper;
062    
063    /** The user directory helper */
064    protected UserDirectoryHelper _userDirectoryHelper;
065
066    private Context _context;
067    
068    @Override
069    public void service(ServiceManager manager) throws ServiceException
070    {
071        super.service(manager);
072        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
073        _organisationChartPageHandler = (OrganisationChartPageHandler) manager.lookup(OrganisationChartPageHandler.ROLE);
074        _contentTypeHelper = (ContentTypesHelper) manager.lookup(ContentTypesHelper.ROLE);
075        _userDirectoryHelper = (UserDirectoryHelper) manager.lookup(UserDirectoryHelper.ROLE);
076    }
077    
078    public void contextualize(Context context) throws ContextException
079    {
080        _context = context;
081    }
082    
083    public boolean supports(Object object)
084    {
085        if (object instanceof Content)
086        {
087            return _isContentUser(object) || _isContentOrgUnit(object);
088        }
089        
090        return false;
091    }
092    
093    @Override
094    protected Set<AmetysObject> _getParents(AmetysObject object)
095    {
096        if (object instanceof Content)
097        {
098            Set<AmetysObject> parents = new HashSet<>();
099            
100            Request request = ContextHelper.getRequest(_context);
101            String originalWorkspace = RequestAttributeWorkspaceSelector.getForcedWorkspace(request);
102            try
103            {
104                RequestAttributeWorkspaceSelector.setForcedWorkspace(request, RepositoryConstants.DEFAULT_WORKSPACE);
105                if (_isContentOrgUnit(object))
106                {
107                    Content parentContent = _organisationChartPageHandler.getParentContent((Content) object);
108                    if (parentContent != null)
109                    {
110                        parents.add(parentContent);
111                    }
112                    else
113                    {
114                        parents.add(_userDirectoryHelper.getUserDirectoryRootContent());
115                    }
116                }
117                else if (_isContentUser(object))
118                {
119                    parents.add(_userDirectoryHelper.getUserDirectoryRootContent());
120                }
121            }
122            finally
123            {
124                RequestAttributeWorkspaceSelector.setForcedWorkspace(request, originalWorkspace);
125            }
126            
127            return parents;
128        }
129        else
130        {
131            return null;
132        }
133    }
134    
135    @Override
136    protected Set< ? extends Object> _convertWorkspaceToRootRightContexts(Set<Object> workspacesContexts)
137    {
138        if (workspacesContexts.contains("/cms"))
139        {
140            try
141            {
142                return Collections.singleton(_userDirectoryHelper.getUserDirectoryRootContent());
143            }
144            catch (UnknownAmetysObjectException e)
145            {
146                // Root does not exist yet
147                return null;
148            }
149        }
150        return null;
151    }
152    
153    private boolean _isContentUser(Object object)
154    {
155        return _contentTypeHelper.isInstanceOf((Content) object, UserDirectoryHelper.ABSTRACT_USER_CONTENT_TYPE);
156    }
157    
158    private boolean _isContentOrgUnit(Object object)
159    {
160        return _contentTypeHelper.isInstanceOf((Content) object, UserDirectoryHelper.ORGUNIT_CONTENT_TYPE);
161    }
162    
163    @Override
164    protected I18nizableText getObjectLabelForExplanation(Object object) throws RightsException
165    {
166        if (object instanceof Content content)
167        {
168            Map<String, I18nizableTextParameter> params = Map.of("title", getObjectLabel(object));
169            if (_isContentUser(content))
170            {
171                return new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_CONTENT_ACCESS_CONTROLLER_USER_CONTEXT_EXPLANATION_LABEL", params);
172            }
173            else if (_isContentOrgUnit(content))
174            {
175                return new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_CONTENT_ACCESS_CONTROLLER_ORGUNIT_CONTEXT_EXPLANATION_LABEL", params);
176            }
177        }
178        else if (_userDirectoryHelper.getUserDirectoryRootContent().equals(object))
179        {
180            return new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_CONTENT_ACCESS_CONTROLLER_ROOT_CONTEXT_EXPLANATION_LABEL");
181        }
182        throw new RightsException("Unsupported object " + object.toString());
183    }
184    
185    public I18nizableText getObjectLabel(Object object) throws RightsException
186    {
187        if (object instanceof Content content)
188        {
189            return new I18nizableText(content.getTitle());
190        }
191        else if (_userDirectoryHelper.getUserDirectoryRootContent().equals(object))
192        {
193            return new I18nizableText("plugin.user-directory", "PLUGINS_USER_DIRECTORY_CONTENT_ACCESS_CONTROLLER_ROOT_CONTEXT_LABEL");
194        }
195        throw new RightsException("Unsupported object " + object.toString());
196    }
197    
198    @Override
199    public I18nizableText getObjectCategory(Object object)
200    {
201        return USER_DIRECTORY_CONTEXT_CATEGORY;
202    }
203    
204    @Override
205    public int getObjectPriority(Object object)
206    {
207        if (_userDirectoryHelper.getUserDirectoryRootContent().equals(object))
208        {
209            return 10;
210        }
211        return super.getObjectPriority(object);
212    }
213}