public Subscription AddSubscription(string username)
        {
            //graph client is used to access graph API (create subscriptions, unpack notifications)
            var graphClient = _tokenisedHttpClientFactory.GetGraphResourceClient();

            //create subscription payload
            var subscriptionPayload = new Subscription
            {
                Resource           = string.Format($"Users('{username}')/events?$filter=contains(subject,'Leave')"),
                ChangeType         = "updated",
                NotificationUrl    = _appSetting.AbsentiaNotificationUrl,
                ClientState        = Guid.NewGuid().ToString(),
                ExpirationDateTime = DateTime.UtcNow + _subscriptionLength
            };
            string contentString = JsonConvert.SerializeObject(subscriptionPayload,
                                                               new JsonSerializerSettings {
                NullValueHandling = NullValueHandling.Ignore
            });


            //assemble into subscriptions request
            string             subscriptionsEndpoint = string.Format($"{_appSetting.MicrosoftGraphResource}/v1.0/subscriptions/");
            HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, subscriptionsEndpoint);

            request.Content = new StringContent(contentString, System.Text.Encoding.UTF8, "application/json");

            // Send the request and parse the response.
            HttpResponseMessage response = graphClient.SendAsync(request).Result;

            if (response.IsSuccessStatusCode)
            {
                // Parse the JSON response.
                string stringResult        = response.Content.ReadAsStringAsync().Result;
                var    createdSubscription = JsonConvert.DeserializeObject <Subscription>(stringResult);
                if (createdSubscription != null)
                {
                    return(createdSubscription);
                }
                throw new ApplicationException(string.Format($"could not deserialize response: {stringResult}"));
            }

            //log error
            var callResult    = response.Content.ReadAsStringAsync().Result;
            var failureReason =
                string.Format($"AddSubscription. HTTP status code:{response.StatusCode}. Error:{callResult}");

            throw new ApplicationException(failureReason);
        }
Exemple #2
0
        public void ProcessNotifications()
        {
            var notifications = _repository.GetPendingNotifications().ToList();

            if (!notifications.Any())
            {
                return;
            }

            //graph client is used to access graph API (create subscriptions, unpack notifications)
            var graphClient = _tokenisedHttpClientFactory.GetGraphResourceClient();
            //outlook client is used to access graph API (update calendars)
            var outlookClient = _tokenisedHttpClientFactory.GetOutlookResourceClient();

            foreach (var notification in notifications)
            {
                try
                {
                    var subscription = _repository.GetSubscription(notification.SubscriptionId);
                    if (subscription == null)
                    {
                        //if the subscription doesnt exist in the database then stop further notifications?
                        _subscriptionService.DeleteSubscription(notification.SubscriptionId);
                        _repository.SetNotificationProcessingResult(notification.NotificationId, true, "Deleted Orphan Subscription");
                        continue;
                    }

                    string             serviceRootUrl = string.Format($"{_setting.MicrosoftGraphResource}/v1.0/");
                    HttpRequestMessage request        = new HttpRequestMessage(HttpMethod.Get, serviceRootUrl + notification.Resource);

                    // Send the 'GET' request to retreive the event
                    var response = graphClient.SendAsync(request).Result;

                    // Get the messages from the JSON response.
                    if (response.IsSuccessStatusCode)
                    {
                        string stringResult = response.Content.ReadAsStringAsync().Result;

                        Event e = JsonConvert.DeserializeObject <Event>(stringResult);

                        //Appogee events have leave type in the body but "Approved Leave" in the subject
                        if (e.BodyPreview.Contains("Leave Type: Working From Home") &&
                            e.Subject.Contains(": Approved Leave"))
                        {
                            var username = _repository.GetUsernameFromSubscription(notification.SubscriptionId);
                            if (string.IsNullOrEmpty(username))
                            {
                                throw new ApplicationException(string.Format($"could not locate subscription '{notification.SubscriptionId}' for notification '{notification.NotificationId}'"));
                            }

                            //for Graph PATCH requests supply only those properties to be updated
                            var update = new
                            {
                                Subject = e.Subject.Replace(": Approved Leave", ": Approved WFH"),
                                ShowAs  = "4"
                            };

                            string patchUrl =
                                string.Format($"{_setting.OutlookResource}/api/v1.0/Users('{username}')/events/{e.Id}");


                            HttpRequestMessage updateRequest = new HttpRequestMessage(new HttpMethod("PATCH"), patchUrl);

                            string contentString = JsonConvert.SerializeObject(update,
                                                                               new JsonSerializerSettings {
                                NullValueHandling = NullValueHandling.Ignore
                            });
                            updateRequest.Content = new StringContent(contentString, System.Text.Encoding.UTF8,
                                                                      "application/json");


                            HttpResponseMessage updateResponse = outlookClient.SendAsync(updateRequest).Result;
                            if (!updateResponse.IsSuccessStatusCode)
                            {
                                throw new ApplicationException(string.Format($"could not update entity: {e.Id}"));
                            }
                            _repository.SetNotificationProcessingResult(notification.NotificationId, true, "processed successfully");
                        }
                        else
                        {
                            _repository.SetNotificationProcessingResult(notification.NotificationId, true, string.Format($"no record to process, did not match predicate: Subject {e.Subject}, Body {e.BodyPreview}"));
                        }
                    }
                    else
                    {
                        throw new ApplicationException(String.Format($"failed processing. status code {response.StatusCode} .message {response.ReasonPhrase}"));
                    }
                }
                catch
                (Exception ex)
                {
                    _repository.SetNotificationProcessingResult(notification.NotificationId, false, ex.Message);
                }
            }
        }