Пример #1
0
        internal static async Task <bool> InsertOrReplaceListWebHook(AzureTableSPWebHook listWebHookRow)
        {
            try
            {
                if (null == Table)
                {
                    CloudTable table = await Utilities.GetCloudTableByName("SharePointWebHooks");
                }

                listWebHookRow.ETag = "*";
                TableOperation insertOrReplace = TableOperation.InsertOrReplace(listWebHookRow);
                await Table.ExecuteAsync(insertOrReplace);

                return(true);
            }
            catch (Exception)
            {
                return(false);
            }
        }
        public static async Task RunAsync([QueueTrigger("processchanges", Connection = "AzureWebJobsStorage")] WebhookNotification notificationModel, ILogger log)
        {
            log.LogInformation($"ProcesResourceChange queue trigger function process Site:{notificationModel.SiteUrl} Resource{notificationModel.Resource} ");

            string tenant  = System.Environment.GetEnvironmentVariable("Tenant", EnvironmentVariableTarget.Process);
            string siteUrl = $"https://{tenant}.sharepoint.com{notificationModel.SiteUrl}";

            log.LogInformation("Getting Azure SharePoint Token");
            LoginEntity loginDetails = await LoginUtil.CertificateLoginDetails();

            OfficeDevPnP.Core.AuthenticationManager authManager = new OfficeDevPnP.Core.AuthenticationManager();

            log.LogInformation("Connecting to SharePoint");
            using (ClientContext clientContext = authManager.GetAzureADAppOnlyAuthenticatedContext(siteUrl, loginDetails.ClientId, loginDetails.Tenant, loginDetails.Certificate))
            {
                log.LogInformation("Getting SharePoint List");
                Guid listId = new Guid(notificationModel.Resource);
                List list   = clientContext.Web.Lists.GetById(listId);

                // grab the changes to the provided list using the GetChanges method
                // on the list. Only request Item changes as that's what's supported via
                // the list web hooks
                ChangeQuery changeQuery = new ChangeQuery(false, false)
                {
                    Item         = true,
                    Add          = true,
                    DeleteObject = false,
                    Update       = true,
                    FetchLimit   = 1000
                };

                ChangeToken lastChangeToken = null;
                if (null == notificationModel.ClientState)
                {
                    throw new ApplicationException("Webhook doesn't contain a Client State");
                }

                Guid id = new Guid(notificationModel.ClientState);
                log.LogInformation("Checking Database for Change Token");
                AzureTableSPWebHook listWebHookRow = await AzureTable.GetListWebHookByID(id, listId);

                if (!string.IsNullOrEmpty(listWebHookRow.LastChangeToken))
                {
                    log.LogInformation("Change Token found");
                    lastChangeToken = new ChangeToken
                    {
                        StringValue = listWebHookRow.LastChangeToken
                    };
                }
                //Start pulling down the changes
                bool allChangesRead = false;

                do
                {
                    if (lastChangeToken == null)
                    {
                        log.LogInformation("Change Token not found grabbing the last 5 days of changes");
                        //If none found, grab only the last 5 day changes.
                        lastChangeToken = new ChangeToken
                        {
                            StringValue = string.Format("1;3;{0};{1};-1", notificationModel.Resource, DateTime.Now.AddDays(-5).ToUniversalTime().Ticks.ToString())
                        };
                    }

                    //Assing the change token to the query..this determins from what point in time we'll receive changes
                    changeQuery.ChangeTokenStart = lastChangeToken;

                    ChangeCollection changes = list.GetChanges(changeQuery);
                    clientContext.Load(list);
                    clientContext.Load(changes);
                    await clientContext.ExecuteQueryAsync();

                    if (changes.Count > 0)
                    {
                        log.LogInformation($"Found {changes.Count} changes");
                        foreach (Change change in changes)
                        {
                            lastChangeToken = change.ChangeToken;

                            if (change is ChangeItem item)
                            {
                                log.LogInformation($"Change {change.ChangeType} on Item:{item.ItemId} on List:{list.Title} Site:{notificationModel.SiteUrl}");
                            }
                        }

                        if (changes.Count < changeQuery.FetchLimit)
                        {
                            allChangesRead = true;
                        }
                    }
                    else
                    {
                        allChangesRead = true;
                    }
                } while (allChangesRead == false);

                if (!listWebHookRow.LastChangeToken.Equals(lastChangeToken.StringValue, StringComparison.InvariantCultureIgnoreCase))
                {
                    listWebHookRow.LastChangeToken = lastChangeToken.StringValue;
                    log.LogInformation("Updating change token");
                    await AzureTable.InsertOrReplaceListWebHook(listWebHookRow);
                }

                if (notificationModel.ExpirationDateTime.AddDays(-30) < DateTime.Now)
                {
                    bool updateResult = list.UpdateWebhookSubscription(new Guid(notificationModel.SubscriptionId), DateTime.Now.AddMonths(2));

                    if (!updateResult)
                    {
                        log.LogError($"The expiration date of web hook {notificationModel.SubscriptionId} with endpoint 'https://{Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME")}/SharePointWebHook' could not be updated");
                    }
                    else
                    {
                        log.LogInformation($"The expiration date of web hook {notificationModel.SubscriptionId} with endpoint 'https://{Environment.GetEnvironmentVariable("WEBSITE_HOSTNAME")}/SharePointWebHook' successfully updated until {DateTime.Now.AddMonths(2).ToLongDateString()} ");
                    }
                }
            }
        }