001/*
002 *  Copyright 2017 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.bpm.workflowsdef;
017
018import java.io.IOException;
019import java.util.ArrayList;
020import java.util.List;
021import java.util.Map;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.context.Context;
025import org.apache.avalon.framework.context.ContextException;
026import org.apache.avalon.framework.context.Contextualizable;
027import org.apache.avalon.framework.service.ServiceException;
028import org.apache.avalon.framework.service.ServiceManager;
029import org.apache.avalon.framework.service.Serviceable;
030import org.apache.cocoon.components.ContextHelper;
031import org.apache.cocoon.environment.Request;
032import org.apache.commons.lang.StringUtils;
033
034import org.ametys.core.user.CurrentUserProvider;
035import org.ametys.core.user.User;
036import org.ametys.core.user.UserIdentity;
037import org.ametys.core.user.UserManager;
038import org.ametys.core.util.I18nUtils;
039import org.ametys.core.util.JSONUtils;
040import org.ametys.core.util.mail.SendMailHelper;
041import org.ametys.plugins.bpm.BPMWorkflowManager;
042import org.ametys.plugins.bpm.jcr.JCRWorkflowProcess;
043import org.ametys.runtime.i18n.I18nizableText;
044import org.ametys.runtime.plugin.component.AbstractLogEnabled;
045
046import com.opensymphony.module.propertyset.PropertySet;
047import com.opensymphony.workflow.FunctionProvider;
048import com.opensymphony.workflow.WorkflowException;
049
050import jakarta.mail.MessagingException;
051/**
052 * Send mail to the users listed in the "users" argument. If the "sendToCreator" argument is present, the mail will also be send to the process creator
053 */
054public class SendProcessMailFunction extends AbstractLogEnabled implements Component, FunctionProvider, Serviceable, Contextualizable
055{
056    /** Actually send the email ? */
057    public static final String SEND_MAIL = "send-request-information-mail";
058    
059    /** The mail subject key. */
060    protected static final String SUBJECT_KEY = "subjectKey";
061    /** The mail body key. */
062    protected static final String BODY_KEY = "bodyKey";
063
064    private JSONUtils _jsonUtils;
065    private UserManager _userManager;
066    private I18nUtils _i18nUtils;
067    private Context _context;
068    private BPMWorkflowManager _bpmWorkflowManager;
069    private CurrentUserProvider _currentUserProvider;
070
071    @Override
072    public void contextualize(Context context) throws ContextException
073    {
074        _context = context;
075    }
076    
077    public void service(ServiceManager manager) throws ServiceException
078    {
079        _bpmWorkflowManager = (BPMWorkflowManager) manager.lookup(BPMWorkflowManager.ROLE);
080        _jsonUtils = (JSONUtils) manager.lookup(JSONUtils.ROLE);
081        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
082        _i18nUtils = (I18nUtils) manager.lookup(I18nUtils.ROLE);
083        _currentUserProvider = (CurrentUserProvider) manager.lookup(CurrentUserProvider.ROLE);
084    }
085    
086    @Override
087    public void execute(Map transientVars, Map args, PropertySet ps) throws WorkflowException
088    {
089        JCRWorkflowProcess process = (JCRWorkflowProcess) transientVars.getOrDefault("process", null);
090        if (process == null)
091        {
092            return;
093        }
094        
095        UserIdentity creator = process.getCreator();
096        User creatorUser = _userManager.getUser(creator);
097        
098        String subjectKey = (String) args.get(SUBJECT_KEY);
099        String bodyKey = (String) args.get(BODY_KEY);
100        String mailSubject = _getSubject(StringUtils.defaultString(subjectKey), process);
101        String mailBody = _getBody(StringUtils.defaultString(bodyKey), process, creatorUser);
102
103        if (mailSubject == null || mailBody == null)
104        {
105            return;
106        }
107
108        List<User> usersList = _getRecipients((String) args.getOrDefault("users", null), (String) args.getOrDefault("sendToCreator", null), creatorUser);
109        
110        List<String> sentTo = new ArrayList<>();
111        for (User user : usersList)
112        {
113            String recipient = user.getEmail();
114            if (StringUtils.isNotEmpty(recipient) && !sentTo.contains(recipient))
115            {
116                try
117                {
118                    SendMailHelper.newMail()
119                                  .withSubject(mailSubject)
120                                  .withTextBody(mailBody)
121                                  .withRecipient(recipient)
122                                  .sendMail();
123                    
124                    sentTo.add(recipient);
125                }
126                catch (MessagingException | IOException e)
127                {
128                    getLogger().warn("Could not send a workflow notification mail to {}", recipient, e);
129                }
130            }
131        }
132        
133    }
134
135    private String _getSubject(String subjectI18nKey, JCRWorkflowProcess process)
136    {
137        List<String> subjectParams = new ArrayList<>();
138        subjectParams.add(process.getTitle());
139        try
140        {
141            String mailSubject = _i18nUtils.translate(new I18nizableText(null, subjectI18nKey, subjectParams), null); // {0}
142            if (mailSubject == null)
143            {
144                getLogger().error("Could not send email for the process workflow, unknown i18n key specified for subject {}", subjectI18nKey);
145            }
146            return mailSubject;
147        }
148        catch (Exception e)
149        {
150            getLogger().error("Could not send email for the process workflow, failed to translate i18n key specified for subject {}", subjectI18nKey, e);
151            return null;
152        }
153    }
154
155    private String _getBody(String bodyI18nKey, JCRWorkflowProcess process, User creatorUser)
156    {
157        List<String> bodyParams = new ArrayList<>();
158        
159        UserIdentity user = _currentUserProvider.getUser();
160        User currentUser = user != null ? _userManager.getUser(user) : null;
161        bodyParams.add(currentUser != null ? currentUser.getFullName() : ""); // {0}
162        bodyParams.add(creatorUser != null ? creatorUser.getFullName() : ""); // {1}
163        bodyParams.add(process.getTitle()); // {2}
164        
165        Request request = ContextHelper.getRequest(_context);
166        String siteName = request.getParameter("site");
167        if (siteName == null)
168        {
169            siteName = (String) request.getAttribute("site");
170        }
171        String lang = request.getParameter("lang");
172        if (lang == null)
173        {
174            lang = (String) request.getAttribute("sitemapLanguage");
175        }
176        
177        bodyParams.add(_bpmWorkflowManager.getProcessPageUrl(process, siteName, lang, true)); // {3}
178        
179        try
180        {
181            String mailBody  = _i18nUtils.translate(new I18nizableText(null, bodyI18nKey, bodyParams), null);
182            if (mailBody == null)
183            {
184                getLogger().error("Could not send email for the process workflow, unknown i18n key specified for body {}", bodyI18nKey);
185            }
186            return mailBody;
187        }
188        catch (Exception e)
189        {
190            getLogger().error("Could not send email for the process workflow, fail to translate i18n key specified for body {}", bodyI18nKey, e);
191            return null;
192        }
193    }
194
195    private List<User> _getRecipients(String users, String sendToCreator, User creatorUser)
196    {
197        List<User> usersList = new ArrayList<>();
198        
199        if (users != null)
200        {
201            for (Object obj : _jsonUtils.convertJsonToList(users))
202            {
203                @SuppressWarnings("unchecked")
204                Map<String, Object> grantedUser = (Map<String, Object>) obj;
205                String login = (String) grantedUser.get("login");
206                String populationId = (String) grantedUser.get("populationId");
207                
208                if (login != null && populationId != null)
209                {
210                    User user = _userManager.getUser(populationId, login);
211                    usersList.add(user);
212                }
213            }
214        }
215        else if ("true".equals(sendToCreator) && creatorUser != null)
216        {
217            usersList.add(creatorUser);
218        }
219        return usersList;
220    }
221}