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[] adminUsers = serviceParameters.getValue("users"); 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(adminUsers, 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 adminUsers the admin users 190 * @param content the created content 191 */ 192 protected void _sendMail(UserIdentity[] adminUsers, WorkflowAwareContent content) 193 { 194 if (adminUsers != 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 for (UserIdentity adminUser : adminUsers) 217 { 218 User user = _userManager.getUser(adminUser); 219 if (user == null) 220 { 221 getLogger().error("Can not send an e-mail for the content creation to the unexisting user " + adminUser); 222 } 223 else 224 { 225 String email = user.getEmail(); 226 try 227 { 228 SendMailHelper.newMail() 229 .withSubject(subject) 230 .withTextBody(body) 231 .withRecipient(email) 232 .sendMail(); 233 } 234 catch (MessagingException | IOException e) 235 { 236 getLogger().warn("Could not send an e-mail for the content creation to " + email, e); 237 } 238 } 239 } 240 } 241 } 242 243 /** 244 * Get the i18n body 245 * @param content the content 246 * @param creatorFullName the creator full name 247 * @param site the site 248 * @return The i18n body 249 */ 250 protected I18nizableText _getI18nBody(WorkflowAwareContent content, String creatorFullName, Site site) 251 { 252 List<String> parametersBody = new ArrayList<>(); 253 parametersBody.add(content.getTitle()); 254 parametersBody.add(creatorFullName); 255 I18nizableText i18nBody = null; 256 if (site != null) 257 { 258 parametersBody.add(_getContentUri(content, site)); 259 parametersBody.add(site.getTitle()); 260 parametersBody.add(site.getUrl()); 261 i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY", parametersBody); 262 } 263 else 264 { 265 i18nBody = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_BODY_NO_SITE", parametersBody); 266 } 267 return i18nBody; 268 } 269 270 /** 271 * Get the i18n subject 272 * @param site the site 273 * @return The i18n subject 274 */ 275 protected I18nizableText _getI18nSubject(Site site) 276 { 277 I18nizableText i18nSubject = null; 278 if (site != null) 279 { 280 List<String> parametersSubject = new ArrayList<>(); 281 parametersSubject.add(site.getTitle()); 282 i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT", parametersSubject); 283 } 284 else 285 { 286 i18nSubject = new I18nizableText("plugin.ugc", "PLUGINS_UGC_SERVICE_FORM_CREATED_CONTENT_MAIL_SUBJECT_NO_SITE"); 287 } 288 return i18nSubject; 289 } 290 291 /** 292 * Get the site name 293 * @param content The content 294 * @return the site name 295 */ 296 protected Site _getSite(WorkflowAwareContent content) 297 { 298 if (content instanceof WebContent) 299 { 300 return ((WebContent) content).getSite(); 301 } 302 303 return null; 304 } 305 306 307 /** 308 * Get the content uri 309 * @param content the content 310 * @param site The site 311 * @return the content uri 312 */ 313 protected String _getContentUri(WorkflowAwareContent content, Site site) 314 { 315 return _getRequestUri() + "/" + site.getName() + "/index.html?uitool=uitool-content,id:%27" + URIUtils.encodeParameter(content.getId()) + "%27"; 316 } 317 318 /** 319 * Get the request URI. 320 * @return the full request URI. 321 */ 322 protected String _getRequestUri() 323 { 324 return StringUtils.stripEnd(StringUtils.removeEndIgnoreCase(Config.getInstance().getValue("cms.url"), "index.html"), "/"); 325 } 326}