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.workspaces.dav;
017
018import java.util.Arrays;
019import java.util.Collections;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.parameters.Parameters;
024import org.apache.cocoon.ResourceNotFoundException;
025import org.apache.cocoon.environment.ObjectModelHelper;
026import org.apache.cocoon.environment.Redirector;
027import org.apache.cocoon.environment.Request;
028import org.apache.cocoon.environment.SourceResolver;
029
030import org.ametys.core.user.UserIdentity;
031import org.ametys.plugins.explorer.resources.ModifiableResourceCollection;
032import org.ametys.plugins.repository.AmetysObject;
033import org.ametys.plugins.workspaces.project.objects.Project;
034import org.ametys.runtime.authentication.AccessDeniedException;
035import org.ametys.runtime.authentication.AuthorizationRequiredException;
036
037/**
038 * Override of org.ametys.cms.rights.CheckReadAccessAction to throw a 404 not found if object is not found, instead of 500
039 */
040public class CheckReadAccessAction extends org.ametys.cms.rights.CheckReadAccessAction
041{
042    private static List<String> CHECK_PARENT_ACCESS_METHODS = Collections.unmodifiableList(Arrays.asList(new String[] {"PUT", "MKCOL"}));
043
044    @Override
045    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
046    {
047        Request request = ObjectModelHelper.getRequest(objectModel);
048        String method = request.getMethod();
049        UserIdentity user = _currentUserProvider.getUser();
050        
051        // Get the Ametys object from either the parameters or the request attributes.
052        AmetysObject ao = getAmetysObject(parameters, request);
053        if (ao == null)
054        {
055            if (CHECK_PARENT_ACCESS_METHODS.contains(method))
056            {
057                String path = parameters.getParameter("path");
058                Project project = (Project) request.getAttribute("project"); 
059                ao = _getFirstParent(project, path);
060            }
061            else
062            {
063                throw new ResourceNotFoundException("Resource not found for path " + parameters.getParameter("objectPath", ""));
064            }
065        }
066        
067        if (_rightManager.hasAnonymousReadAccess(ao))
068        {
069            // Anonymous access allowed
070            return EMPTY_MAP;
071        }
072        else if (user == null)
073        {
074            // User not yet authenticated
075            throw new AuthorizationRequiredException();
076        }
077        else if (_rightManager.hasReadAccess(user, ao))
078        {
079            // User has read access
080            return null;
081        }
082        
083        // User is not authorized
084        throw new AccessDeniedException("Access to object " + ao.getId() + " is not allowed for user " + user);
085    }
086    
087    private AmetysObject _getFirstParent(Project project, String path)
088    {
089        ModifiableResourceCollection parent = _resolver.resolveByPath(project.getPath() + "/ametys-internal:resources/");
090        for (String folder : path.split("/"))
091        {
092            if (folder.isEmpty())
093            {
094                continue;
095            }
096            if (!parent.hasChild(folder))
097            {
098                return parent;
099            }
100            parent = parent.getChild(folder);
101        }
102        return null;
103    }
104}