diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c1a5bba2..bdfc62818 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -65,6 +65,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ### Removed - Removed `-RemoveExisting` parameter from `Add-PnPAzureADGroupMember`, `Add-PnPAzureADGroupOwner`, `Add-PnPMicrosoft365GroupMember` and `Add-PnPMicrosoft365GroupOwner` cmdlets. It was never really implemented and without function. [#5153](https://github.com/pnp/powershell/pull/5153) +- Deprecated `Get-PnPSearchCrawlLog` cmdlet as the underlying API has been deprecated by Microsoft and no longer returns results. The cmdlet now throws a `NotSupportedException` and will be removed in a future version. ### Contributors diff --git a/documentation/Get-PnPSearchCrawlLog.md b/documentation/Get-PnPSearchCrawlLog.md index 332b113e5..b2a368ce4 100644 --- a/documentation/Get-PnPSearchCrawlLog.md +++ b/documentation/Get-PnPSearchCrawlLog.md @@ -9,6 +9,9 @@ online version: https://pnp.github.io/powershell/cmdlets/Get-PnPSearchCrawlLog.h # Get-PnPSearchCrawlLog +> [!CAUTION] +> **This cmdlet has been deprecated.** The underlying API has been deprecated by Microsoft and no longer returns results. This cmdlet will be removed in a future version of PnP PowerShell. + ## SYNOPSIS Returns entries from the SharePoint search crawl log. Make sure you are granted access to the crawl log via the SharePoint search admin center at https://-admin.sharepoint.com/_layouts/15/searchadmin/crawllogreadpermission.aspx in order to run this cmdlet. diff --git a/resources/predictor/PnP.PowerShell.Suggestions.nightly.json b/resources/predictor/PnP.PowerShell.Suggestions.nightly.json index 8eaefa04e..92bd1bc9a 100644 --- a/resources/predictor/PnP.PowerShell.Suggestions.nightly.json +++ b/resources/predictor/PnP.PowerShell.Suggestions.nightly.json @@ -4355,48 +4355,6 @@ "Id": 726, "Rank": 8 }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog", - "Id": 727, - "Rank": 1 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -Filter \"https://contoso-my.sharepoint.com/personal\"", - "Id": 728, - "Rank": 2 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -ContentSource UserProfiles", - "Id": 729, - "Rank": 3 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -ContentSource UserProfiles -Filter \"mikael\"", - "Id": 730, - "Rank": 4 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -ContentSource Sites -LogLevel Error -RowLimit 10", - "Id": 731, - "Rank": 5 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -EndDate (Get-Date).AddDays(-100)", - "Id": 732, - "Rank": 6 - }, - { - "CommandName": "Get-PnPSearchCrawlLog", - "Command": "Get-PnPSearchCrawlLog -RowLimit 3 -RawFormat", - "Id": 733, - "Rank": 7 - }, { "CommandName": "Get-PnPSearchExternalConnection", "Command": "Get-PnPSearchExternalConnection", diff --git a/src/Commands/Search/GetSearchCrawlLog.cs b/src/Commands/Search/GetSearchCrawlLog.cs index 9567ebbbf..5da0626d2 100644 --- a/src/Commands/Search/GetSearchCrawlLog.cs +++ b/src/Commands/Search/GetSearchCrawlLog.cs @@ -35,6 +35,7 @@ public class CrawlEntry [Cmdlet(VerbsCommon.Get, "PnPSearchCrawlLog", DefaultParameterSetName = "Xml")] [ApiNotAvailableUnderApplicationPermissions] + [Obsolete("The underlying API for this cmdlet has been deprecated by Microsoft and no longer returns results. This cmdlet will be removed in a future version.")] public class GetSearchCrawlLog : PnPWebCmdlet { [Parameter(Mandatory = false)] @@ -62,153 +63,8 @@ public class GetSearchCrawlLog : PnPWebCmdlet protected override void ExecuteCmdlet() { - try - { - var crawlLog = new DocumentCrawlLog(ClientContext, ClientContext.Site); - ClientContext.Load(crawlLog); - - int contentSourceId; - switch (ContentSource) - { - case ContentSource.Sites: - contentSourceId = GetContentSourceIdForSites(crawlLog); - break; - case ContentSource.UserProfiles: - contentSourceId = GetContentSourceIdForUserProfiles(crawlLog); - break; - default: - throw new ArgumentOutOfRangeException(); - } - - string postFilter = string.Empty; - if (string.IsNullOrWhiteSpace(Filter) && ContentSource == ContentSource.Sites) - { - Filter = $"https://{GetHostName()}.sharepoint.{PnP.Framework.AuthenticationManager.GetSharePointDomainSuffix(Connection.AzureEnvironment)}"; - } - - int origLimit = RowLimit; - if (ContentSource == ContentSource.UserProfiles) - { - postFilter = Filter; - Filter = $"https://{GetHostName()}-my.sharepoint.{PnP.Framework.AuthenticationManager.GetSharePointDomainSuffix(Connection.AzureEnvironment)}"; - RowLimit = MaxRows; - } - - var logEntries = crawlLog.GetCrawledUrls(false, RowLimit, Filter, true, contentSourceId, (int)LogLevel, -1, StartDate, EndDate); - ClientContext.ExecuteQueryRetry(); - - if (RawFormat) - { - var entries = new List(); - foreach (var dictionary in logEntries.Value.Rows) - { - string url = System.Net.WebUtility.UrlDecode(dictionary["FullUrl"].ToString()); - if (ContentSource == ContentSource.UserProfiles && contentSourceId == -1) - { - if (!url.Contains(":443/person")) continue; - } - if (string.IsNullOrWhiteSpace(postFilter) || url.Contains(postFilter)) - { - entries.Add(ConvertToPSObject(dictionary)); - } - } - WriteObject(entries.Take(origLimit), true); - } - else - { - var entries = new List(logEntries.Value.Rows.Count); - foreach (var dictionary in logEntries.Value.Rows) - { - var entry = MapCrawlLogEntry(dictionary); - if (string.IsNullOrWhiteSpace(postFilter) || entry.Url.Contains(postFilter)) - { - entries.Add(entry); - } - } - - if (ContentSource == ContentSource.UserProfiles && contentSourceId == -1) - { - // Crawling has changed and uses one content source - // Need to apply post-filter to pull out profile entries only - entries = - entries.Where(e => System.Net.WebUtility.UrlDecode(e.Url.ToString()).ToLower().Contains(":443/person")) - .ToList(); - } - WriteObject(entries.Take(origLimit).OrderByDescending(i => i.CrawlTime).ToList(), true); - } - } - catch (Exception e) - { - LogError($"Error: {e.Message}. Make sure you are granted access to the crawl log via the SharePoint search admin center at https://-admin.sharepoint.com/_layouts/15/searchadmin/crawllogreadpermission.aspx"); - } + throw new NotSupportedException("The underlying API for Get-PnPSearchCrawlLog has been deprecated by Microsoft and no longer returns results. This cmdlet will be removed in a future version."); } -#region Helper functions - - private string GetHostName() - { - return new Uri(ClientContext.Url).Host.Replace("-admin", "").Replace("-public", "").Replace("-my", "").Replace($".sharepoint.{PnP.Framework.AuthenticationManager.GetSharePointDomainSuffix(Connection.AzureEnvironment)}", ""); - } - - private int GetContentSourceIdForSites(DocumentCrawlLog crawlLog) - { - var hostName = GetHostName(); - var spContent = crawlLog.GetCrawledUrls(false, 10, $"https://{hostName}.sharepoint.{PnP.Framework.AuthenticationManager.GetSharePointDomainSuffix(Connection.AzureEnvironment)}/sites", true, -1, (int)LogLevel.All, -1, DateTime.Now.AddDays(-100), DateTime.Now.AddDays(1)); - ClientContext.ExecuteQueryRetry(); - if (spContent.Value.Rows.Count > 0) return (int)spContent.Value.Rows.First()["ContentSourceID"]; - return -1; - } - - private int GetContentSourceIdForUserProfiles(DocumentCrawlLog crawlLog) - { - var hostName = GetHostName(); - var peopleContent = crawlLog.GetCrawledUrls(false, 100, $"sps3s://{hostName}-my.sharepoint.{PnP.Framework.AuthenticationManager.GetSharePointDomainSuffix(Connection.AzureEnvironment)}", true, -1, (int)LogLevel.All, -1, DateTime.Now.AddDays(-100), DateTime.Now.AddDays(1)); - ClientContext.ExecuteQueryRetry(); - if (peopleContent.Value.Rows.Count > 0) return (int)peopleContent.Value.Rows.First()["ContentSourceID"]; - return -1; - } - - private static CrawlEntry MapCrawlLogEntry(Dictionary dictionary) - { - var entry = new CrawlEntry - { - ItemId = (int)dictionary["URLID"], - ContentSourceId = (int)dictionary["ContentSourceID"], - Url = dictionary["FullUrl"].ToString(), - CrawlTime = (DateTime)dictionary["TimeStampUtc"] - }; - long.TryParse(dictionary["LastRepositoryModifiedTime"] + "", out long ticks); - if (ticks != 0) - { - var itemDate = DateTime.FromFileTimeUtc(ticks); - entry.ItemTime = itemDate; - } - entry.LogLevel = - (LogLevel)Enum.Parse(typeof(LogLevel), dictionary["ErrorLevel"].ToString()); - - - entry.Status = dictionary["StatusMessage"] + ""; - entry.Status += dictionary["ErrorDesc"] + ""; - var errorCode = int.Parse(dictionary["ErrorCode"]+""); - if (!string.IsNullOrWhiteSpace(entry.Status) || errorCode != 0) - { - entry.LogLevel = LogLevel.Warning; - } - return entry; - } - - private object ConvertToPSObject(IDictionary r) - { - PSObject res = new PSObject(); - if (r != null) - { - foreach (var kvp in r) - { - res.Properties.Add(new PSNoteProperty(kvp.Key, kvp.Value)); - } - } - return res; - } -#endregion } }