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.HashMap;
019import java.util.List;
020import java.util.Map;
021import java.util.Objects;
022
023import org.apache.avalon.framework.component.Component;
024import org.apache.avalon.framework.service.ServiceException;
025import org.apache.avalon.framework.service.ServiceManager;
026import org.apache.avalon.framework.service.Serviceable;
027import org.apache.commons.lang.StringUtils;
028
029import org.ametys.core.right.RightManager;
030import org.ametys.core.ui.Callable;
031import org.ametys.core.user.User;
032import org.ametys.core.user.UserManager;
033import org.ametys.plugins.forms.dao.FormDAO;
034import org.ametys.plugins.forms.repository.Form;
035import org.ametys.plugins.repository.AmetysObjectResolver;
036import org.ametys.runtime.authentication.AccessDeniedException;
037import org.ametys.runtime.plugin.component.AbstractLogEnabled;
038import org.ametys.web.repository.page.Page;
039
040/**
041 * The helper to schedule opening of form
042 */
043public class FormInvitationsHelper extends AbstractLogEnabled implements Serviceable, Component
044{
045    /** Avalon ROLE. */
046    public static final String ROLE = FormInvitationsHelper.class.getName();
047    
048    /** Ametys object resolver. */
049    protected AmetysObjectResolver _resolver;
050    
051    /** The users manager */
052    protected UserManager _userManager;
053    
054    /** The right manager */
055    protected RightManager _rightManager;
056    
057    /** The limited entries helper */
058    protected LimitedEntriesHelper _limitedEntriesHelper;
059    
060    /** The form DAO */
061    protected FormDAO _formDAO;
062    
063    /** The form mail helper */
064    protected FormMailHelper _formMailHelper;
065    
066    public void service(ServiceManager manager) throws ServiceException
067    {
068        _resolver = (AmetysObjectResolver) manager.lookup(AmetysObjectResolver.ROLE);
069        _userManager = (UserManager) manager.lookup(UserManager.ROLE);
070        _rightManager = (RightManager) manager.lookup(RightManager.ROLE);
071        _limitedEntriesHelper = (LimitedEntriesHelper) manager.lookup(LimitedEntriesHelper.ROLE);
072        _formDAO = (FormDAO) manager.lookup(FormDAO.ROLE);
073        _formMailHelper = (FormMailHelper) manager.lookup(FormMailHelper.ROLE);
074    }
075    
076    /**
077     * Sends invitations emails.
078     * @param formId The id of the form.
079     * @param message The message content.
080     * @param siteName The site name.
081     * @param language the language
082     * @return An empty map
083     */
084    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
085    public Map<String, Object> sendInvitations (String formId, String message, String siteName, String language)
086    {
087        Form form = _resolver.resolveById(formId);
088        _formDAO.checkHandleFormRight(form);
089        
090        List<Page> pages = _getFormPages(formId, siteName);
091        if (pages.isEmpty())
092        {
093            throw new AccessDeniedException("Can't send invitations for form id '" + formId + "' because it is not published.");
094        }
095        
096        _formMailHelper.sendInvitationMails(form, _getUsersToInvite(form), message);
097        return new HashMap<>();
098    }
099
100    private List<Page> _getFormPages(String formId, String siteName)
101    {
102        List<Page> pages = _formDAO.getFormPage(formId, siteName)
103            .stream()
104            .filter(Page.class::isInstance)
105            .map(Page.class::cast)
106            .toList();
107        return pages;
108    }
109    
110    /**
111     * Get users to invite to the form (user with mail and who are not answered yet to the form)
112     * @param form the form
113     * @return the users to invite
114     */
115    protected List<User> _getUsersToInvite(Form form)
116    {
117        // Can invite users if the form is on anonymous read access
118        if (_rightManager.hasAnonymousReadAccess(form))
119        {
120            return List.of();
121        }
122        
123        return _rightManager.getReadAccessAllowedUsers(form).resolveAllowedUsers(true)
124                    .stream()
125                    .filter(id -> !_limitedEntriesHelper.hasUserAlreadyAnswer(form, id, null)) // User who are not answered yet
126                    .map(id -> _userManager.getUser(id)) // Get user object
127                    .filter(Objects::nonNull) // User not null
128                    .filter(u -> StringUtils.isNotEmpty(u.getEmail())) // User with a mail
129                    .toList();
130    }
131    
132    /**
133     * Get users to invite to the form (user with mail and who are not answered yet to the form)
134     * @param formId The id of the form.
135     * @return The number of users to invite
136     */
137    @Callable (rights = Callable.SKIP_BUILTIN_CHECK)
138    public int getNbOfUsersToInvite(String formId)
139    {
140        Form form = _resolver.resolveById(formId);
141        _formDAO.checkHandleFormRight(form);
142        
143        return _getUsersToInvite(form).size();
144    }
145}