001/* 002 * Copyright 2018 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.ugc.actions; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.avalon.framework.parameters.Parameters; 025import org.apache.avalon.framework.service.ServiceException; 026import org.apache.avalon.framework.service.ServiceManager; 027import org.apache.cocoon.acting.ServiceableAction; 028import org.apache.cocoon.environment.ObjectModelHelper; 029import org.apache.cocoon.environment.Redirector; 030import org.apache.cocoon.environment.Request; 031import org.apache.cocoon.environment.SourceResolver; 032import org.apache.commons.lang.StringUtils; 033 034import org.ametys.cms.contenttype.ContentType; 035import org.ametys.cms.contenttype.ContentTypeExtensionPoint; 036import org.ametys.cms.contenttype.ContentTypesHelper; 037import org.ametys.cms.repository.Content; 038import org.ametys.cms.repository.WorkflowAwareContent; 039import org.ametys.core.captcha.CaptchaHelper; 040import org.ametys.core.cocoon.ActionResultGenerator; 041import org.ametys.core.user.CurrentUserProvider; 042import org.ametys.core.user.User; 043import org.ametys.core.user.UserIdentity; 044import org.ametys.core.user.UserManager; 045import org.ametys.core.util.I18nUtils; 046import org.ametys.core.util.JSONUtils; 047import org.ametys.core.util.URIUtils; 048import org.ametys.core.util.mail.SendMailHelper; 049import org.ametys.plugins.repository.AmetysObjectResolver; 050import org.ametys.plugins.repository.data.holder.ModelAwareDataHolder; 051import org.ametys.plugins.ugc.UGCConstants; 052import org.ametys.runtime.config.Config; 053import org.ametys.runtime.i18n.I18nizableText; 054import org.ametys.web.cache.PageHelper; 055import org.ametys.web.content.FOContentCreationHelper; 056import org.ametys.web.repository.content.WebContent; 057import org.ametys.web.repository.page.Page; 058import org.ametys.web.repository.page.ZoneItem; 059import org.ametys.web.repository.site.Site; 060 061import com.google.common.collect.ArrayListMultimap; 062import com.google.common.collect.Multimap; 063 064import jakarta.mail.MessagingException; 065 066/** 067 * Create content action 068 */ 069public class ProposeContentAction extends ServiceableAction 070{ 071 private static final int _INITIAL_ACTION_ID = 1111; 072 073 /** Ametys object resolver. */ 074 protected AmetysObjectResolver _resolver; 075 076 /** The content type extension point */ 077 protected ContentTypeExtensionPoint _cTypeEP; 078 079 /** The content type helper */ 080 protected ContentTypesHelper _contentTypeHelper; 081 082 /** The JSON Utils */ 083 protected JSONUtils _jsonUtils; 084 085 /** The current user provider */ 086 protected CurrentUserProvider _currentUserProvider; 087 088 /** The I18n utils */ 089 protected I18nUtils _i18nUtils; 090 091 /** The user manager */ 092 protected UserManager _userManager; 093 094 /** Helper for FO content creation */ 095 protected FOContentCreationHelper _foContentCreationHelper; 096 097 /** The page helper */ 098 protected PageHelper _pageHelper; 099 100 @Override 101 public void service(ServiceManager serviceManager) throws ServiceException 102 { 103 super.service(serviceManager); 104 _resolver = (AmetysObjectResolver) serviceManager.lookup(AmetysObjectResolver.ROLE); 105 _cTypeEP = (ContentTypeExtensionPoint) serviceManager.lookup(ContentTypeExtensionPoint.ROLE); 106 _contentTypeHelper = (ContentTypesHelper) serviceManager.lookup(ContentTypesHelper.ROLE); 107 _jsonUtils = (JSONUtils) serviceManager.lookup(JSONUtils.ROLE); 108 _currentUserProvider = (CurrentUserProvider) serviceManager.lookup(CurrentUserProvider.ROLE); 109 _i18nUtils = (I18nUtils) serviceManager.lookup(I18nUtils.ROLE); 110 _userManager = (UserManager) serviceManager.lookup(UserManager.ROLE); 111 _foContentCreationHelper = (FOContentCreationHelper) serviceManager.lookup(FOContentCreationHelper.ROLE); 112 _pageHelper = (PageHelper) serviceManager.lookup(PageHelper.ROLE); 113 } 114 115 public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception 116 { 117 Map<String, Object> result = new HashMap<>(); 118 119 Multimap<String, I18nizableText> errors = ArrayListMultimap.create(); 120 121 Request request = ObjectModelHelper.getRequest(objectModel); 122 123 String zoneId = request.getParameter("zoneId"); 124 ZoneItem zoneItem = _resolver.resolveById(zoneId); 125 Page page = zoneItem.getParent().getParent().getParent().getParent(); 126 127 ModelAwareDataHolder serviceParameters = zoneItem.getServiceParameters(); 128 String workflowName = serviceParameters.getValue("workflow"); 129 String contentTypeId = serviceParameters.getValue("content-type"); 130 UserIdentity adminUser = serviceParameters.getValue("user"); 131 132 String siteName = request.getParameter("site"); 133 String language = request.getParameter("lang"); 134 135 ContentType ugcMixin = _cTypeEP.getExtension(UGCConstants.UGC_MIXIN_TYPE); 136 137 ContentType contentType = _cTypeEP.getExtension(contentTypeId); 138 Map<String, Object> values = _foContentCreationHelper.getAndValidateFormValues(request, contentType, "main", errors); 139 values.putAll(_foContentCreationHelper.getAndValidateFormValues(request, ugcMixin, "main", errors)); 140 141 // Check captcha if needed 142 if (_pageHelper.isCaptchaRequired(page)) 143 { 144 String captchaValue = request.getParameter("captcha"); 145 String captchaKey = request.getParameter("captcha-key"); 146 147 // Validate the input 148 if (!CaptchaHelper.checkAndInvalidate(captchaKey, captchaValue)) 149 { 150 errors.put("captcha", new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_ERROR_INVALID_CAPTCHA")); 151 } 152 } 153 154 // If there are no errors 155 if (errors.isEmpty()) 156 { 157 String title = request.getParameter("title"); 158 159 // we add a prefix to the title for the content name to prevent issue with numeric title 160 String prefix = StringUtils.substringAfterLast(contentTypeId, "."); 161 162 result = _foContentCreationHelper.createAndEditContent(_INITIAL_ACTION_ID, new String[] {contentTypeId}, new String[] {UGCConstants.UGC_MIXIN_TYPE}, siteName, prefix + "-" + title, title, language, values, workflowName, null, new HashMap<String, Object>()); 163 164 if (result.containsKey(Content.class.getName())) 165 { 166 result.put("success", true); 167 168 // Send mail 169 WorkflowAwareContent content = (WorkflowAwareContent) result.get(Content.class.getName()); 170 _sendMail(adminUser, content); 171 } 172 else 173 { 174 result.put("success", false); 175 } 176 } 177 else 178 { 179 result.put("success", false); 180 result.put("errors", _jsonUtils.convertObjectToJson(errors.asMap())); 181 } 182 183 request.setAttribute(ActionResultGenerator.MAP_REQUEST_ATTR, result); 184 return EMPTY_MAP; 185 } 186 187 /** 188 * Send mail to inform that a content is created 189 * @param adminUser the admin user 190 * @param content the created content 191 */ 192 protected void _sendMail(UserIdentity adminUser, WorkflowAwareContent content) 193 { 194 if (adminUser != null) 195 { 196 String creatorFullName = null; 197 UserIdentity creatorIdentity = _currentUserProvider.getUser(); 198 if (creatorIdentity != null) 199 { 200 User creator = _userManager.getUser(creatorIdentity); 201 creatorFullName = creator.getFullName(); 202 } 203 else 204 { 205 creatorFullName = content.getValue(UGCConstants.ATTRIBUTE_PATH_UGC_AUTHOR); 206 } 207 208 Site site = _getSite(content); 209 210 I18nizableText i18nSubject = _getI18nSubject(site); 211 I18nizableText i18nBody = _getI18nBody(content, creatorFullName, site); 212 213 String subject = _i18nUtils.translate(i18nSubject); 214 String body = _i18nUtils.translate(i18nBody); 215 216 User user = _userManager.getUser(adminUser); 217 if (user == null) 218 { 219 getLogger().error("Can not send an e-mail for the content creation to the unexisting user " + adminUser); 220 } 221 else 222 { 223 String email = user.getEmail(); 224 try 225 { 226 SendMailHelper.newMail() 227 .withSubject(subject) 228 .withTextBody(body) 229 .withRecipient(email) 230 .sendMail(); 231 } 232 catch (MessagingException | IOException e) 233 { 234 getLogger().warn("Could not send an e-mail for the content creation to " + email, e); 235 } 236 } 237 } 238 } 239 240 /** 241 * Get the i18n body 242 * @param content the content 243 * @param creatorFullName the creator full name 244 * @param site the site 245 * @return The i18n body 246 */ 247 protected I18nizableText _getI18nBody(WorkflowAwareContent content, String creatorFullName, Site site) 248 { 249 List<String> parametersBody = new ArrayList<>(); 250 parametersBody.add(content.getTitle()); 251 parametersBody.add(creatorFullName); 252 I18nizableText i18nBody = null; 253 if (site != null) 254 { 255 parametersBody.add(_getContentUri(content, site)); 256 parametersBody.add(site.getTitle()); 257 parametersBody.add(site.getUrl()); 258 i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY", parametersBody); 259 } 260 else 261 { 262 i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY_NO_SITE", parametersBody); 263 } 264 return i18nBody; 265 } 266 267 /** 268 * Get the i18n subject 269 * @param site the site 270 * @return The i18n subject 271 */ 272 protected I18nizableText _getI18nSubject(Site site) 273 { 274 I18nizableText i18nSubject = null; 275 if (site != null) 276 { 277 List<String> parametersSubject = new ArrayList<>(); 278 parametersSubject.add(site.getTitle()); 279 i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT", parametersSubject); 280 } 281 else 282 { 283 i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT_NO_SITE"); 284 } 285 return i18nSubject; 286 } 287 288 /** 289 * Get the site name 290 * @param content The content 291 * @return the site name 292 */ 293 protected Site _getSite(WorkflowAwareContent content) 294 { 295 if (content instanceof WebContent) 296 { 297 return ((WebContent) content).getSite(); 298 } 299 300 return null; 301 } 302 303 304 /** 305 * Get the content uri 306 * @param content the content 307 * @param site The site 308 * @return the content uri 309 */ 310 protected String _getContentUri(WorkflowAwareContent content, Site site) 311 { 312 return _getRequestUri() + "/" + site.getName() + "/index.html?uitool=uitool-content,id:%27" + URIUtils.encodeParameter(content.getId()) + "%27"; 313 } 314 315 /** 316 * Get the request URI. 317 * @return the full request URI. 318 */ 319 protected String _getRequestUri() 320 { 321 return StringUtils.stripEnd(StringUtils.removeEndIgnoreCase(Config.getInstance().getValue("cms.url"), "index.html"), "/"); 322 } 323}