001/*
002 *  Copyright 2022 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.forms.helper;
017
018import java.util.ArrayList;
019import java.util.HashMap;
020import java.util.List;
021import java.util.Map;
022import java.util.Optional;
023import java.util.regex.Pattern;
024
025import org.apache.avalon.framework.component.Component;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.avalon.framework.service.Serviceable;
029import org.apache.commons.collections.ListUtils;
030import org.apache.commons.lang3.ArrayUtils;
031import org.apache.commons.lang3.StringUtils;
032
033import org.ametys.core.ui.Callable;
034import org.ametys.plugins.forms.dao.FormDAO;
035import org.ametys.plugins.forms.repository.Form;
036import org.ametys.plugins.repository.AmetysObjectResolver;
037import org.ametys.runtime.plugin.component.AbstractLogEnabled;
038
039/**
040 * The helper to handle admin emails
041 */
042public class FormAdminMailsHelper extends AbstractLogEnabled implements Serviceable, Component
043{
044    /** Avalon ROLE. */
045    public static final String ROLE = FormAdminMailsHelper.class.getName();
046    
047    /** Pattern for admin mails */
048    public static final String REGEX_MAIL = "^([a-zA-Z0-9_\\.\\-])+\\@(([a-zA-Z0-9\\-])+\\.)+([a-zA-Z0-9]{2,})$";
049    
050    /** Ametys object resolver. */
051    protected AmetysObjectResolver _resolver;
052    
053    /** The form DAO */
054    protected FormDAO _formDAO;
055    
056    public void service(ServiceManager manager) throws ServiceException
057    {
058        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
059        _formDAO = (FormDAO) manager.lookup(FormDAO.ROLE);
060    }
061    
062    /**
063     * Get the entries admin emails
064     * @param formId Id of the form
065     * @return the map of admin emails
066     */
067    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
068    public Map<String, Object> getAdminEmails(String formId)
069    {
070        Form form = _resolver.resolveById(formId);
071        _formDAO.checkHandleFormRight(form);
072        
073        Map<String, Object> emailProperties = new HashMap<> ();
074        _addOptionalProperty(Form.ADMIN_EMAILS, form.getAdminEmails(), emailProperties, ArrayUtils.EMPTY_STRING_ARRAY);
075        _addOptionalProperty(Form.ADMIN_EMAILS_OTHER, form.getOtherAdminEmails(), emailProperties, StringUtils.EMPTY);
076        _addOptionalProperty(Form.ADMIN_EMAIL_SUBJECT, form.getAdminEmailSubject(), emailProperties, null);
077        _addOptionalProperty(Form.ADMIN_EMAIL_BODY, form.getAdminEmailBody(), emailProperties, null);
078        
079        return emailProperties;
080    }
081    
082    private void _addOptionalProperty(String propertyName, Optional<? extends Object> value, Map<String, Object> limitProperties, Object defaultValue)
083    {
084        if (value.isPresent())
085        {
086            limitProperties.put(propertyName, value.get());
087        }
088        else if (defaultValue != null)
089        {
090            limitProperties.put(propertyName, defaultValue);
091        }
092    }
093    
094    /**
095     * Get the entries admin emails
096     * @param formId Id of the form
097     * @param emails mails of the admin
098     * @param receiver name of the form question to get receiver email from, can be null
099     * @param subject subject of the admin email
100     * @param body body of the admin email
101     * @return the map of results
102     */
103    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
104    public Map<String, Object> setAdminEmails(String formId, String emails, String receiver, String subject, String body)
105    {
106        Map<String, Object> result = new HashMap<>();
107        
108        Form form = _resolver.resolveById(formId);
109        _formDAO.checkHandleFormRight(form);
110        
111        //Check regex
112        String[] emailsTab = emails.split("[ ,;\r]");
113        List<String> computedEmails = getValidAdminEmails(emailsTab);
114        
115        if (!computedEmails.isEmpty() || StringUtils.isNotBlank(receiver))
116        {
117            form.setAdminEmails(computedEmails.toArray(new String[computedEmails.size()]));
118            if (StringUtils.isBlank(receiver) && form.hasValue(Form.ADMIN_EMAILS_OTHER))
119            {
120                form.removeValue(Form.ADMIN_EMAILS_OTHER);
121            }
122            if (StringUtils.isNotBlank(receiver))
123            {
124                form.setOtherAdminEmails(receiver);
125            }
126            form.setAdminEmailSubject(subject);
127            form.setAdminEmailBody(body);
128            form.saveChanges();
129        }
130        else
131        {
132            getLogger().error("Mails addresses were undefined or not valid");
133            result.put("message", "invalid-address");
134        }
135        
136        return result;
137    }
138
139    /**
140     * Unset the properties relative to the admin emails 
141     * @param formId The id ofthe current form
142     * @return the map of results
143     */
144    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
145    public Map<String, Object> removeAdminEmails(String formId)
146    {
147        Map<String, Object> result = new HashMap<>();
148        
149        Form form = _resolver.resolveById(formId);
150        _formDAO.checkHandleFormRight(form);
151        
152        if (form.getAdminEmails().isPresent() || form.getOtherAdminEmails().isPresent())
153        {
154            if (form.getAdminEmails().isPresent())
155            {
156                form.removeValue(Form.ADMIN_EMAILS);
157            }
158            if (form.getOtherAdminEmails().isPresent())
159            {
160                form.removeValue(Form.ADMIN_EMAILS_OTHER);
161            }
162            form.removeValue(Form.ADMIN_EMAIL_SUBJECT);
163            form.removeValue(Form.ADMIN_EMAIL_BODY);
164
165            form.saveChanges();
166        }
167        
168        return result;
169    }
170    
171    /**
172     * Check if an array of emails are valid and returns them without spaces
173     * @param emailsTab the emails to check
174     * @return the emails trimed or an empty list if they are not valids
175     */
176    public List<String> getValidAdminEmails(String[] emailsTab)
177    {
178        Pattern pattern = Pattern.compile(REGEX_MAIL);
179        List<String> computedEmails = new ArrayList<>();
180        boolean error = false;
181        for (String mail : emailsTab)
182        {
183            String trimMail = mail.trim();
184            if (StringUtils.isNotBlank(trimMail))
185            {
186                if (pattern.matcher(trimMail).matches())
187                {
188                    computedEmails.add(trimMail);
189                }
190                else
191                {
192                    error = true;
193                    getLogger().error("Mail address " + mail + " did not match regex");
194                }
195            }
196        }
197        return error ? ListUtils.EMPTY_LIST : computedEmails;
198    }
199}