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.plugins.webcontentio;
017
018import java.io.InputStream;
019import java.util.ArrayList;
020import java.util.HashMap;
021import java.util.List;
022import java.util.Map;
023
024import org.ametys.core.authentication.token.AuthenticationTokenManager;
025import org.ametys.core.cocoon.ActionResultGenerator;
026import org.ametys.core.right.RightsException;
027import org.ametys.core.user.UserIdentity;
028import org.ametys.plugins.repository.AmetysRepositoryException;
029import org.ametys.web.repository.page.SitemapElement;
030import org.ametys.web.repository.site.Site;
031import org.ametys.web.repository.site.SiteManager;
032import org.ametys.web.repository.sitemap.Sitemap;
033import org.apache.avalon.framework.context.ContextException;
034import org.apache.avalon.framework.context.Contextualizable;
035import org.apache.avalon.framework.parameters.Parameters;
036import org.apache.avalon.framework.service.ServiceException;
037import org.apache.avalon.framework.service.ServiceManager;
038import org.apache.cocoon.Constants;
039import org.apache.cocoon.acting.ServiceableAction;
040import org.apache.cocoon.environment.Context;
041import org.apache.cocoon.environment.ObjectModelHelper;
042import org.apache.cocoon.environment.Redirector;
043import org.apache.cocoon.environment.Request;
044import org.apache.cocoon.environment.SourceResolver;
045import org.apache.cocoon.servlet.multipart.Part;
046import org.apache.commons.lang.StringUtils;
047
048/**
049 * Action to import a content from an input stream received through a POST request.
050 */
051public class ImportContentAction extends ServiceableAction implements Contextualizable
052{
053    private AuthenticationTokenManager _authenticationManager;
054    private ContentIOManager _contentIOManager;
055    private SiteManager _siteManager;
056
057    private Context _context;
058
059    @Override
060    public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException
061    {
062        _context = (Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT);
063    }
064    
065    @Override
066    public void service(ServiceManager smanager) throws ServiceException
067    {
068        super.service(smanager);
069        
070        _authenticationManager = (AuthenticationTokenManager) manager.lookup(AuthenticationTokenManager.ROLE);
071        _contentIOManager = (ContentIOManager) manager.lookup(ContentIOManager.ROLE);
072        _siteManager = (SiteManager) manager.lookup(SiteManager.ROLE);
073    }
074    
075    @Override
076    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
077    {
078        Request request = ObjectModelHelper.getRequest(objectModel);
079        List<String> error = new ArrayList<>();
080        Boolean success = true;
081        
082        if (!"POST".equals(request.getMethod()))
083        {
084            success = false;
085            error.add("Only POST methods are allowed.");
086            getLogger().warn("Only POST methods are allowed.");
087        }
088        
089        Object content = request.get("content");
090        if (content == null)
091        {
092            success = false;
093            error.add("No content provided. The parameter 'content' is mandatory.");
094            getLogger().warn("No content provided. The parameter 'content' is mandatory.");
095        }
096        
097        String authenticationToken = (String) request.get("key");
098        if (authenticationToken == null)
099        {
100            success = false;
101            error.add("No API key provided. The parameter 'key' is mandatory.");
102            getLogger().warn("No API key provided. The parameter 'key' is mandatory.");
103        }
104        
105        UserIdentity user = _authenticationManager.validateToken(authenticationToken);
106        if (user == null)
107        {
108            success = false;
109            error.add("The API key provided is invalid, please check the value of the parameter 'key'.");
110            getLogger().warn("The API key provided is invalid, please check the value of the parameter 'key'.");
111        }
112        
113        String siteName = parameters.getParameter("site");
114        String sitemapName = parameters.getParameter("sitemap");
115        String path = parameters.getParameter("path");
116        boolean extern = parameters.getParameterAsBoolean("extern", false);
117        
118        SitemapElement rootPage = getPageFromPath(siteName, sitemapName, path);
119        
120        if (rootPage == null)
121        {
122            success = false;
123            error.add("Unable to retrieve the parent page, the specified path was not found.");
124            getLogger().warn("Unable to retrieve the parent page, the specified path was not found.");
125        }
126        
127        if (success && content instanceof Part)
128        {
129            Part part = (Part) content;
130            
131            InputStream is = part.getInputStream();
132            String contentName = part.getUploadName();
133            String mimeType = _context.getMimeType(contentName);
134            
135            try
136            {
137                _contentIOManager.importContent(is, mimeType, contentName, user, rootPage, extern);
138            }
139            catch (RightsException e)
140            {
141                success = false;
142                error.add("Insufficient rights to create a content.");
143                getLogger().warn("Insufficient rights to create a content.");
144            }
145        }
146        
147        Map<String, Object> mapResult = new HashMap<>();
148        mapResult.put("success", success);
149        if (!success)
150        {
151            mapResult.put("error", error);
152        }
153        
154        request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, mapResult);
155        
156        return EMPTY_MAP;
157    }
158    
159    private SitemapElement getPageFromPath(String siteName, String sitemapName, String path)
160    {
161        Site site = null;
162        Sitemap sitemap = null;
163        
164        try
165        {
166            site = _siteManager.getSite(siteName);
167            sitemap = site.getSitemap(sitemapName);
168        }
169        catch (AmetysRepositoryException e)
170        {
171            getLogger().warn("Unable to retrieve the site or sitemap.", e);
172            return null;
173        }
174        
175        if (StringUtils.isEmpty(path) || "/".equals(path))
176        {
177            return sitemap;
178        }
179        
180        String pathCleaned = path;
181        if (pathCleaned.startsWith("/"))
182        {
183            pathCleaned = pathCleaned.substring(1);
184        }
185        if (pathCleaned.endsWith("/"))
186        {
187            pathCleaned = pathCleaned.substring(0, path.length() - 1);
188        }
189
190        String[] pagesName = pathCleaned.split("/");
191        
192        SitemapElement page = sitemap;
193        for (int i = 0; i < pagesName.length; i++)
194        {
195            if (StringUtils.isEmpty(pagesName[i]))
196            {
197                return null;
198            }
199            
200            page = page.getChild(pagesName[i]);
201            
202            if (page == null)
203            {
204                return null;
205            }
206        }
207        
208        return page;
209        
210    }
211}