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.bluemind;
017
018import java.time.LocalDateTime;
019import java.util.ArrayList;
020import java.util.Collections;
021import java.util.Date;
022import java.util.HashMap;
023import java.util.List;
024import java.util.Map;
025
026import org.ametys.core.user.UserIdentity;
027import org.ametys.core.util.DateUtils;
028import org.ametys.plugins.messagingconnector.AbstractMessagingConnector;
029import org.ametys.plugins.messagingconnector.CalendarEvent;
030import org.ametys.plugins.messagingconnector.EmailMessage;
031import org.ametys.plugins.messagingconnector.MessagingConnectorException;
032import org.ametys.runtime.config.Config;
033
034import net.bluemind.authentication.api.IAuthentication;
035import net.bluemind.authentication.api.LoginResponse;
036import net.bluemind.calendar.api.CalendarContainerType;
037import net.bluemind.calendar.api.ICalendar;
038import net.bluemind.calendar.api.VEvent;
039import net.bluemind.core.api.date.BmDateTime;
040import net.bluemind.core.api.date.BmDateTimeWrapper;
041import net.bluemind.core.api.fault.ServerFault;
042import net.bluemind.core.container.model.ItemValue;
043import net.bluemind.core.rest.http.ClientSideServiceProvider;
044import net.bluemind.mailbox.api.IMailboxes;
045import net.bluemind.user.api.IUser;
046
047/**
048 * 
049 * The connector used by the messaging connector plugin when the bluemind mail server is used.
050 * Implements the methods of the MessagingConnector interface in order to get the  informations from the mail server
051 *
052 */
053public class BluemindConnector extends AbstractMessagingConnector
054{
055    /**
056     * The bluemind server core URL (for instance
057     * http://bluemind.myserver.com/services)
058     */
059    protected String _bmCoreUrl;
060
061    /** The administrator login. */
062    protected String _adminLogin;
063
064    /** An API key generated by the above administrator account. */
065    protected String _apiKey;
066    
067    /** The BlueMind domain (for instance myserver.com) */
068    protected String _domain;
069
070    /** The serviceProvider to establish the connection*/
071    protected ClientSideServiceProvider _serviceProvider;
072
073    @Override
074    public void initialize()
075    {
076        super.initialize();
077        _bmCoreUrl = Config.getInstance().getValue("bluemind.server.url");
078        _adminLogin = Config.getInstance().getValue("bluemind.admin.login");
079        _apiKey = Config.getInstance().getValue("bluemind.api.key");
080        _domain = Config.getInstance().getValue("bluemind.domain");
081
082        LoginResponse resp = ClientSideServiceProvider.getProvider(_bmCoreUrl, null).instance(IAuthentication.class).login(_adminLogin, _apiKey, BluemindConnector.class.getName());
083        _serviceProvider = ClientSideServiceProvider.getProvider(_bmCoreUrl, resp.authKey);
084    }
085    
086    private String _getUserAuthKey(UserIdentity userIdentity)
087    {
088        return _serviceProvider.instance(IAuthentication.class).su(userIdentity.getLogin() + "@" + _domain).authKey;
089    }
090    
091    private ClientSideServiceProvider _getServiceUserProvider(UserIdentity userIdentity)
092    {
093        String authKey = _getUserAuthKey(userIdentity);
094        return ClientSideServiceProvider.getProvider(_bmCoreUrl, authKey);
095    }
096    
097    /**
098     * Get the events information from the bluemind server.
099     * @param userIdentity the user identity.
100     * @param maxDays The maximum number of days from now to search the events
101     * @return the events information as a Map.
102     * @throws MessagingConnectorException if an error occurs.
103     */
104    protected Map<String, Object> getEventsInfo(UserIdentity userIdentity, int maxDays) throws MessagingConnectorException
105    {
106        ClientSideServiceProvider userProvider = null;
107        
108        try
109        {
110            userProvider = _getServiceUserProvider(userIdentity);
111            
112            if (userProvider == null)
113            {
114                throw new MessagingConnectorException("Bluemind authentification failed for user " + userIdentity);
115            }
116            
117            Map<String, Object> userInfo = new HashMap<>();
118            
119            LocalDateTime nowLdt = LocalDateTime.now();
120            Date fromDate = DateUtils.asDate(nowLdt.withSecond(0));
121            Date untilDate = DateUtils.asDate(nowLdt.withHour(0).withMinute(0).withSecond(0).plusDays(maxDays));
122
123            IUser userClient = _serviceProvider.instance(IUser.class, _domain);
124            String userCalendar = CalendarContainerType.defaultUserCalendar(userClient.byEmail(userIdentity.getLogin() + "@" + _domain).uid);
125            List<VEvent> listEvents = new ArrayList<>();
126            ICalendar calendar = userProvider.instance(ICalendar.class, userCalendar);
127            List<String> listUid = calendar.all();
128            for (String uid : listUid)
129            {
130                ItemValue<VEvent> itemEvent = calendar.getComplete(uid);
131                VEvent event = new VEvent();
132                event = itemEvent.value;
133                BmDateTimeWrapper bmdTimeWrapper = new BmDateTimeWrapper(event.dtstart);
134                if (bmdTimeWrapper.toDate().getTime() >= fromDate.getTime() && bmdTimeWrapper.toDate().getTime() <= untilDate.toInstant().toEpochMilli())
135                {
136                    listEvents.add(event);
137                }
138            }
139
140            userInfo.put("events", listEvents);
141
142            return userInfo;
143        }
144        catch (ServerFault e)
145        {
146            throw new MessagingConnectorException("Failed to get Bluemind informations for user " + userIdentity, e);
147        }
148        finally
149        {
150            if (userProvider != null)
151            {
152                userProvider.instance(IAuthentication.class).logout();
153            }
154        }
155    }
156    
157    @SuppressWarnings("unchecked")
158    @Override
159    protected List<CalendarEvent> internalGetEvents(UserIdentity userIdentity, int maxDays, int maxEvents) throws MessagingConnectorException
160    {
161        List<CalendarEvent> calendar = new ArrayList<>();
162        
163        Map<String, Object> userInfo = getEventsInfo(userIdentity, maxDays);
164        List<VEvent> listEvents = (List<VEvent>) userInfo.get("events");
165        for (VEvent event : listEvents)
166        {
167            if (calendar.size() < maxEvents)
168            {
169                //Changing from BmDateTime to Date
170                BmDateTime begin = event.dtstart;
171                BmDateTime end = event.dtend;
172                Long dateBegin = BmDateTimeWrapper.toTimeZonedTimeStamp(begin.iso8601, begin.timezone);
173                Long dateEnd = BmDateTimeWrapper.toTimeZonedTimeStamp(end.iso8601, end.timezone);
174                
175                //Creating the event
176                CalendarEvent newEvent = new CalendarEvent();
177                newEvent.setEndDate(new Date(dateEnd));
178                newEvent.setStartDate(new Date(dateBegin));
179                if (event.summary != null)
180                {
181                    newEvent.setSubject(event.summary);
182                }
183                if (event.location != null)
184                {
185                    newEvent.setLocation(event.location);
186                }
187                calendar.add(newEvent);
188            }
189        }
190        return calendar;
191
192    }
193
194    @SuppressWarnings("unchecked")
195    @Override
196    protected int internalGetEventsCount(UserIdentity userIdentity, int maxDays) throws MessagingConnectorException
197    {
198        Map<String, Object> userInfo = getEventsInfo(userIdentity, maxDays);
199        return ((List<VEvent>) userInfo.get("events")).size();
200    }
201
202    @Override
203    protected List<EmailMessage> internalGetEmails(UserIdentity userIdentity, int maxEmails) throws MessagingConnectorException
204    {
205        // Not implement for bluemind
206        return Collections.EMPTY_LIST;
207    }
208
209    @Override
210    protected int internalGetEmailsCount(UserIdentity userIdentity) throws MessagingConnectorException
211    {
212        ClientSideServiceProvider userProvider = null;
213
214        try
215        {
216            userProvider = _getServiceUserProvider(userIdentity);
217            
218            if (userProvider == null)
219            {
220                throw new MessagingConnectorException("Bluemind authentification failed for user " + userIdentity);
221            }
222            
223            IMailboxes mailboxes = userProvider.instance(IMailboxes.class, _domain);
224            return mailboxes.getUnreadMessagesCount();
225        }
226        catch (ServerFault e)
227        {
228            throw new MessagingConnectorException("Fail to get email count for user " + userIdentity, e);
229        }
230        finally
231        {
232            if (userProvider != null)
233            {
234                userProvider.instance(IAuthentication.class).logout();
235            }
236        }
237    }
238}