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.CHECKED_BY_IMPLEMENTATION)
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_LANGUAGE, form.getAdminEmailLanguage(), emailProperties, null);
077        _addOptionalProperty(Form.ADMIN_EMAIL_SUBJECT, form.getAdminEmailSubject(), emailProperties, null);
078        _addOptionalProperty(Form.ADMIN_EMAIL_BODY, form.getAdminEmailBody(), emailProperties, null);
079        
080        return emailProperties;
081    }
082    
083    private void _addOptionalProperty(String propertyName, Optional<? extends Object> value, Map<String, Object> limitProperties, Object defaultValue)
084    {
085        if (value.isPresent())
086        {
087            limitProperties.put(propertyName, value.get());
088        }
089        else if (defaultValue != null)
090        {
091            limitProperties.put(propertyName, defaultValue);
092        }
093    }
094    
095    /**
096     * Get the entries admin emails
097     * @param formId Id of the form
098     * @param emails mails of the admin
099     * @param receiver name of the form question to get receiver email from, can be null
100     * @param subject subject of the admin email
101     * @param body body of the admin email
102     * @param language The language to use in the admin mail
103     * @return the map of results
104     */
105    @Callable (rights = Callable.CHECKED_BY_IMPLEMENTATION)
106    public Map<String, Object> setAdminEmails(String formId, String emails, String receiver, String subject, String body, String language)
107    {
108        Map<String, Object> result = new HashMap<>();
109        
110        Form form = _resolver.resolveById(formId);
111        _formDAO.checkHandleFormRight(form);
112        
113        //Check regex
114        String[] emailsTab = emails.split("[ ,;\r]");
115        List<String> computedEmails = getValidAdminEmails(emailsTab);
116        
117        if (!computedEmails.isEmpty() || StringUtils.isNotBlank(receiver))
118        {
119            form.setAdminEmails(computedEmails.toArray(new String[computedEmails.size()]));
120            if (StringUtils.isBlank(receiver) && form.hasValue(Form.ADMIN_EMAILS_OTHER))
121            {
122                form.removeValue(Form.ADMIN_EMAILS_OTHER);
123            }
124            if (StringUtils.isNotBlank(receiver))
125            {
126                form.setOtherAdminEmails(receiver);
127            }
128            
129            form.setAdminEmailLanguage(language);
130            form.setAdminEmailSubject(subject);
131            form.setAdminEmailBody(body);
132            form.saveChanges();
133        }
134        else
135        {
136            getLogger().error("Mails addresses were undefined or not valid");
137            result.put("message", "invalid-address");
138        }
139        
140        return result;
141    }
142
143    /**
144     * Unset the properties relative to the admin emails
145     * @param formId The id ofthe current form
146     * @return the map of results
147     */
148    @Callable (rights = Callable.CHECKED_BY_IMPLEMENTATION)
149    public Map<String, Object> removeAdminEmails(String formId)
150    {
151        Map<String, Object> result = new HashMap<>();
152        
153        Form form = _resolver.resolveById(formId);
154        _formDAO.checkHandleFormRight(form);
155        
156        if (form.getAdminEmails().isPresent() || form.getOtherAdminEmails().isPresent())
157        {
158            if (form.getAdminEmails().isPresent())
159            {
160                form.removeValue(Form.ADMIN_EMAILS);
161            }
162            if (form.getOtherAdminEmails().isPresent())
163            {
164                form.removeValue(Form.ADMIN_EMAILS_OTHER);
165            }
166            form.removeValue(Form.ADMIN_EMAIL_SUBJECT);
167            form.removeValue(Form.ADMIN_EMAIL_BODY);
168
169            form.saveChanges();
170        }
171        
172        return result;
173    }
174    
175    /**
176     * Check if an array of emails are valid and returns them without spaces
177     * @param emailsTab the emails to check
178     * @return the emails trimed or an empty list if they are not valids
179     */
180    public List<String> getValidAdminEmails(String[] emailsTab)
181    {
182        Pattern pattern = Pattern.compile(REGEX_MAIL);
183        List<String> computedEmails = new ArrayList<>();
184        boolean error = false;
185        for (String mail : emailsTab)
186        {
187            String trimMail = mail.trim();
188            if (StringUtils.isNotBlank(trimMail))
189            {
190                if (pattern.matcher(trimMail).matches())
191                {
192                    computedEmails.add(trimMail);
193                }
194                else
195                {
196                    error = true;
197                    getLogger().error("Mail address " + mail + " did not match regex");
198                }
199            }
200        }
201        return error ? ListUtils.EMPTY_LIST : computedEmails;
202    }
203}