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