001/* 002 * Copyright 2015 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.web.clientsideelement; 017 018import java.io.IOException; 019import java.util.ArrayList; 020import java.util.HashMap; 021import java.util.HashSet; 022import java.util.List; 023import java.util.Map; 024import java.util.Set; 025import java.util.stream.Collectors; 026 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.commons.lang3.StringUtils; 030 031import org.ametys.core.group.Group; 032import org.ametys.core.group.GroupIdentity; 033import org.ametys.core.group.GroupManager; 034import org.ametys.core.ui.Callable; 035import org.ametys.core.ui.ClientSideElement; 036import org.ametys.core.ui.mail.StandardMailBodyHelper; 037import org.ametys.core.ui.mail.StandardMailBodyHelper.MailBodyBuilder; 038import org.ametys.core.user.User; 039import org.ametys.core.user.UserIdentity; 040import org.ametys.core.user.UserManager; 041import org.ametys.core.util.I18nUtils; 042import org.ametys.core.util.language.UserLanguagesManager; 043import org.ametys.core.util.mail.SendMailHelper; 044import org.ametys.plugins.core.user.UserHelper; 045import org.ametys.runtime.config.Config; 046import org.ametys.runtime.i18n.I18nizableText; 047import org.ametys.runtime.i18n.I18nizableTextParameter; 048import org.ametys.web.repository.page.Page; 049import org.ametys.web.repository.site.Site; 050 051import jakarta.mail.MessagingException; 052 053/** 054 * This {@link ClientSideElement} creates a button that will be enabled if page and its hierarchy is valid. 055 * 056 */ 057public class LivePageClientSideElement extends AbstractPageClientSideElement 058{ 059 /** The {@link UserManager} */ 060 private UserManager _userManager; 061 062 /** The {@link UserManager} for front-end users */ 063 private UserManager _foUsersManager; 064 065 /** The {@link GroupManager} for front-end groups */ 066 private GroupManager _foGroupsManager; 067 068 /** The {@link I18nUtils} */ 069 private I18nUtils _i18nUtils; 070 071 private UserHelper _userHelper; 072 073 private UserLanguagesManager _userLanguagesManager; 074 075 @Override 076 public void service(ServiceManager smanager) throws ServiceException 077 { 078 super.service(smanager); 079 _userManager = (UserManager) smanager.lookup(UserManager.ROLE); 080 _foUsersManager = (UserManager) smanager.lookup(UserManager.ROLE); 081 _foGroupsManager = (GroupManager) smanager.lookup(GroupManager.ROLE); 082 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 083 _userHelper = (UserHelper) smanager.lookup(UserHelper.ROLE); 084 _userLanguagesManager = (UserLanguagesManager) smanager.lookup(UserLanguagesManager.ROLE); 085 } 086 087 /** 088 * Send a notification for online pages. 089 * @param pageIds the ids of the pages 090 * @param users the users that will be notified 091 * @param groups the groups that will be notified 092 * @param comment the comment of the notifier 093 * @return the result 094 */ 095 @Callable (rights = Callable.CHECKED_BY_IMPLEMENTATION) 096 public Map<String, Object> sendOnlineNotification(List<String> pageIds, List<Map<String, String>> users, List<Map<String, String>> groups, String comment) 097 { 098 List<String> allRightIds = new ArrayList<>(); 099 List<Map<String, Object>> noRightPages = new ArrayList<>(); 100 101 UserIdentity userIdentity = _currentUserProvider.getUser(); 102 User notifier = _userManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin()); 103 104 List<UserIdentity> userIdentities = new ArrayList<>(); 105 for (Map<String, String> user : users) 106 { 107 UserIdentity ui = _userHelper.json2userIdentity(user); 108 if (ui != null) 109 { 110 userIdentities.add(ui); 111 } 112 } 113 List<GroupIdentity> groupIdentities = new ArrayList<>(); 114 for (Map<String, String> group : groups) 115 { 116 String id = group.get("groupId"); 117 String groupDirectory = group.get("groupDirectory"); 118 groupIdentities.add(new GroupIdentity(id, groupDirectory)); 119 } 120 121 Map<String, Set<User>> distinctUsersByLanguage = _getDistinctUsersByLanguage(userIdentities, groupIdentities); 122 123 for (String pageId : pageIds) 124 { 125 Page page = _resolver.resolveById(pageId); 126 127 if (!hasRight(page)) 128 { 129 noRightPages.add(Map.of("id", pageId, "title", page.getTitle())); 130 } 131 else 132 { 133 allRightIds.add(pageId); 134 135 String from = _getSender(notifier, page); 136 for (String language : distinctUsersByLanguage.keySet()) 137 { 138 String subject = _getSubject(notifier, page, language); 139 140 for (User user : distinctUsersByLanguage.get(language)) 141 { 142 String email = user.getEmail(); 143 if (StringUtils.isNotEmpty(email)) 144 { 145 try 146 { 147 String body = _getBody(notifier, user, page, comment, language); 148 149 SendMailHelper.newMail() 150 .withSubject(subject) 151 .withHTMLBody(body) 152 .withSender(from) 153 .withRecipient(email) 154 .sendMail(); 155 } 156 catch (MessagingException | IOException e) 157 { 158 getLogger().error("Unable to send mail to user " + user.getEmail(), e); 159 } 160 } 161 } 162 } 163 164 } 165 } 166 167 return Map.of("allright-pages", allRightIds, "noright-pages", noRightPages); 168 } 169 170 /** 171 * Get the email sender 172 * @param sender The user responsible for the action 173 * @param page The published page 174 * @return The sender 175 */ 176 private String _getSender (User sender, Page page) 177 { 178 if (sender != null && sender.getEmail() != null) 179 { 180 return sender.getFullName() + " <" + sender.getEmail() + ">"; 181 } 182 183 Site site = page.getSite(); 184 String defaultFromValue = Config.getInstance().getValue("smtp.mail.from"); 185 return site.getValue("site-mail-from", false, defaultFromValue); 186 } 187 188 /** 189 * Get the email subject 190 * @param sender The user responsible for the notification 191 * @param page The published page 192 * @return The email subject 193 */ 194 private String _getSubject (User sender, Page page, String language) 195 { 196 Site site = page.getSite(); 197 198 Map<String, I18nizableTextParameter> subjectI18nParameters = new HashMap<>(); 199 subjectI18nParameters.put("user", new I18nizableText(sender.getFullName())); 200 subjectI18nParameters.put("siteTitle", new I18nizableText(site.getTitle())); 201 subjectI18nParameters.put("pageTitle", new I18nizableText(page.getTitle())); 202 203 I18nizableText msg = new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_SUBJECT", subjectI18nParameters); 204 205 return _i18nUtils.translate(msg, language); 206 } 207 208 /** 209 * Get the email body 210 * @param sender The user responsible for the notification 211 * @param user The recipient of the notification 212 * @param page The published page 213 * @param comment The user's comment. Can be empty or null. 214 * @return The email body 215 * @throws IOException if faile dto build HTML mail body 216 */ 217 private String _getBody (User sender, User user, Page page, String comment, String language) throws IOException 218 { 219 Site site = page.getSite(); 220 String pageUrl = site.getUrl() + "/" + page.getSitemap().getName() + "/" + page.getPathInSitemap() + ".html"; 221 222 Map<String, I18nizableTextParameter> i18nParams = new HashMap<>(); 223 i18nParams.put("sender", new I18nizableText(sender.getFullName())); 224 i18nParams.put("user", new I18nizableText(user.getFullName())); 225 i18nParams.put("siteTitle", new I18nizableText(site.getTitle())); 226 i18nParams.put("siteUrl", new I18nizableText(site.getUrl())); 227 i18nParams.put("pageTitle", new I18nizableText(page.getTitle())); 228 i18nParams.put("pageUrl", new I18nizableText(pageUrl)); 229 if (StringUtils.isNotEmpty(comment)) 230 { 231 String htmlComment = comment.replaceAll("\r?\n", "<br/>"); 232 i18nParams.put("comment", new I18nizableText(htmlComment)); 233 } 234 235 MailBodyBuilder bodyBuilder = StandardMailBodyHelper.newHTMLBody() 236 .withTitle(new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_BODY_TITLE", i18nParams)) 237 .addMessage(new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_BODY", i18nParams)) 238 .addMessage(new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_BODY_LINK_TEXT", i18nParams)) 239 .withLanguage(language) 240 .withLink(pageUrl, new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_BODY_LINK_BUTTON")); 241 242 if (StringUtils.isNotEmpty(comment)) 243 { 244 bodyBuilder.addMessage(new I18nizableText("plugin.web", "PLUGINS_WEB_PAGE_NOTIFY_ONLINE_PUBLICATION_MAIL_BODY_COMMENT", i18nParams)); 245 } 246 247 return bodyBuilder.build(); 248 } 249 250 private Map<String, Set<User>> _getDistinctUsersByLanguage (List<UserIdentity> userIdentities, List<GroupIdentity> groupIdentities) 251 { 252 Set<User> users = new HashSet<>(); 253 254 for (UserIdentity userIdentity : userIdentities) 255 { 256 if (userIdentity != null && StringUtils.isNotEmpty(userIdentity.getLogin()) && StringUtils.isNotEmpty(userIdentity.getPopulationId())) 257 { 258 User user = _foUsersManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin()); 259 if (user != null) 260 { 261 users.add(user); 262 } 263 } 264 } 265 266 for (GroupIdentity groupIdentity : groupIdentities) 267 { 268 if (groupIdentity != null && StringUtils.isNotEmpty(groupIdentity.getId()) && StringUtils.isNotEmpty(groupIdentity.getDirectoryId())) 269 { 270 Group group = _foGroupsManager.getGroup(groupIdentity.getDirectoryId(), groupIdentity.getId()); 271 if (group != null) 272 { 273 Set<UserIdentity> groupUsers = group.getUsers(); 274 for (UserIdentity userIdentity : groupUsers) 275 { 276 User user = _foUsersManager.getUser(userIdentity.getPopulationId(), userIdentity.getLogin()); 277 if (user != null) 278 { 279 users.add(user); 280 } 281 } 282 } 283 } 284 } 285 286 String defaultLanguage = _userLanguagesManager.getDefaultLanguage(); 287 288 return users.stream() 289 .collect(Collectors.groupingBy( 290 user -> { 291 // user.getLanguage() can be null and groupingBy never accept null keys 292 return StringUtils.defaultIfBlank(user.getLanguage(), defaultLanguage); 293 }, 294 Collectors.toSet() 295 ) 296 ); 297 } 298}