001/*
002 *  Copyright 2023 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.usermanagement;
017
018import java.io.File;
019import java.io.FileInputStream;
020import java.io.IOException;
021import java.nio.charset.StandardCharsets;
022import java.util.List;
023import java.util.Map;
024
025import org.apache.avalon.framework.parameters.Parameters;
026import org.apache.avalon.framework.service.ServiceException;
027import org.apache.avalon.framework.service.ServiceManager;
028import org.apache.cocoon.acting.ServiceableAction;
029import org.apache.cocoon.environment.ObjectModelHelper;
030import org.apache.cocoon.environment.Redirector;
031import org.apache.cocoon.environment.Request;
032import org.apache.cocoon.environment.SourceResolver;
033import org.apache.cocoon.servlet.multipart.Part;
034import org.apache.cocoon.servlet.multipart.PartOnDisk;
035import org.apache.cocoon.servlet.multipart.RejectedPart;
036import org.apache.commons.io.FilenameUtils;
037import org.apache.commons.io.IOUtils;
038import org.apache.commons.io.input.BOMInputStream;
039import org.quartz.SchedulerException;
040
041import org.ametys.core.cocoon.JSonReader;
042import org.ametys.core.user.CurrentUserProvider;
043import org.ametys.plugins.core.schedule.Scheduler;
044import org.ametys.web.WebHelper;
045
046/**
047 * Import user to invit from a CSV or text file.
048 */
049public class ImportInvitationsAction extends ServiceableAction
050{
051    private static final String[] _ALLOWED_EXTENSIONS = new String[] {"txt", "csv"};
052    private Scheduler _scheduler;
053    private CurrentUserProvider _currentUserProvider;
054    
055    @Override
056    public void service(ServiceManager smanager) throws ServiceException
057    {
058        super.service(smanager);
059        _scheduler = (Scheduler) smanager.lookup(Scheduler.ROLE);
060        _currentUserProvider = (CurrentUserProvider) smanager.lookup(CurrentUserProvider.ROLE);
061    }
062    
063    public Map act(Redirector redirector, SourceResolver resolver, Map objectModel, String source, Parameters parameters) throws Exception
064    {
065        Request request = ObjectModelHelper.getRequest(objectModel);
066
067        Part part = (Part) request.get("file");
068        if (part instanceof RejectedPart)
069        {
070            request.setAttribute(JSonReader.OBJECT_TO_READ, Map.of("success", false, "error", "rejected-file"));
071            return EMPTY_MAP;
072        }
073        
074        PartOnDisk uploadedFilePart = (PartOnDisk) part;
075        File uploadedFile = (uploadedFilePart != null) ? uploadedFilePart.getFile() : null;
076        String filename = (uploadedFilePart != null) ? uploadedFilePart.getFileName().toLowerCase() : null;
077        
078        if (!FilenameUtils.isExtension(filename, _ALLOWED_EXTENSIONS))
079        {
080            request.setAttribute(JSonReader.OBJECT_TO_READ, Map.of("success", false, "error", "invalid-extension"));
081            return EMPTY_MAP;
082        }
083        
084        try (FileInputStream fileIS =  new FileInputStream(uploadedFile); 
085                BOMInputStream bomIS = new BOMInputStream(fileIS))
086        {
087            List<String> guestLines = IOUtils.readLines(bomIS, StandardCharsets.UTF_8);
088            
089            String populationAndUserDirectory = request.getParameter("userDirectory");
090            String[] split = populationAndUserDirectory.split("#");
091            String populationId = split[0];
092            String userDirectoryId = split[1];
093            String siteName = WebHelper.getSiteName(request);
094            
095            boolean resendInvitation = "true".equals(request.getParameter("resendInvitations"));
096            
097            // Schedule the sending of invitations
098            _scheduler.scheduleJob(new SendInvitationsRunnable(guestLines, siteName, populationId, userDirectoryId, resendInvitation, _currentUserProvider.getUser()));
099            
100        }
101        catch (IOException e)
102        {
103            getLogger().error("Failed to read file to send invitations from CSV file", e);
104            request.setAttribute(JSonReader.OBJECT_TO_READ, Map.of("success", false, "error", "file-error"));
105            return EMPTY_MAP;
106        }
107        catch (SchedulerException e)
108        {
109            getLogger().error("An exception occurred while trying to schedule the sending of invitations", e);
110            request.setAttribute(JSonReader.OBJECT_TO_READ, Map.of("success", false, "error", "schedule-error"));
111            return EMPTY_MAP;
112        }
113        
114        request.setAttribute(JSonReader.OBJECT_TO_READ, Map.of("success", true));
115        return EMPTY_MAP;
116    }
117
118}