From c31ee0fe597cf710b51b923a81f7fb8196b94103 Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 28 Jun 2022 10:49:08 +0200 Subject: [PATCH 1/2] Fixes #2041 --- CHANGELOG.md | 3 + .../Get-PnPSiteCollectionAppCatalog.md | 84 +++++++++++++++++++ .../Get-PnPSiteCollectionAppCatalogs.md | 38 --------- .../Admin/GetSiteCollectionAppCatalog.cs | 69 +++++++++++++++ .../Admin/GetSiteCollectionAppCatalogs.cs | 19 ----- src/Commands/Admin/GetTenantSite.cs | 1 - .../SharePoint/SiteCollectionAppCatalog.cs | 26 ++++++ 7 files changed, 182 insertions(+), 58 deletions(-) create mode 100644 documentation/Get-PnPSiteCollectionAppCatalog.md delete mode 100644 documentation/Get-PnPSiteCollectionAppCatalogs.md create mode 100644 src/Commands/Admin/GetSiteCollectionAppCatalog.cs delete mode 100644 src/Commands/Admin/GetSiteCollectionAppCatalogs.cs create mode 100644 src/Commands/Model/SharePoint/SiteCollectionAppCatalog.cs diff --git a/CHANGELOG.md b/CHANGELOG.md index c34329d07..4b8e52522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,6 +63,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added `Get-Microsoft365GroupYammerCommunity` cmdlet to retrieve details on the Yammer Community connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) - Added `Get-Microsoft365GroupTeam` cmdlet to retrieve details on the Microsoft Teams team connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) - Added `Get-Microsoft365GroupEndpoints` cmdlet to retrieve details on all endpoints connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) +- Added `-ExcludeDeletedSites` optional parameter to `Get-PnPSiteCollectionAppCatalogs` which allows for site collections with App Catalogs that are in the recycle bin to be exluded from the results ### Changed @@ -80,6 +81,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Changed that almost every cmdlet now supports passing in a specific connection using `-Connection`. If omitted, the default connection will be used. [#1949](https://github.com/pnp/powershell/pull/1949), [#2011](https://github.com/pnp/powershell/pull/2011), [#1958](https://github.com/pnp/powershell/pull/1958) - Changed connecting with `Connect-PnPOnline -Credentials` now throwing a clear exception when making a typo in the hostname instead of getting stuck [#686](https://github.com/pnp/pnpframework/pull/686) - Changed `Get-PnPHubSiteChild` to have its `-Identity` parameter become optional. If not provided, the currently connected to site will be used. [#2033](https://github.com/pnp/powershell/pull/2033) +- Changed `Get-PnPSiteCollectionAppCatalogs` (plural) to `Get-PnPSiteCollectionAppCatalog` (singular) to follow the naming convention ### Fixed @@ -112,6 +114,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Fixed `Get-PnPHubSiteChild` throwing an exception when passing in a URL that is actually not a hub site [#2033](https://github.com/pnp/powershell/pull/2033) - Fixed `Add-PnPListItem` not showing field name when it has an improper value assigned to it [#2002](https://github.com/pnp/powershell/pull/2002) - Fixed connecting using `Connect-PnPOnline -Interactive -ClientId` not working well when already having an App-Only connection using the same ClientId [#2035](https://github.com/pnp/powershell/pull/2035) +- Fixed `Get-PnPSiteCollectionAppCatalog` not returning updated site collection URLs if they had been renamed ### Removed diff --git a/documentation/Get-PnPSiteCollectionAppCatalog.md b/documentation/Get-PnPSiteCollectionAppCatalog.md new file mode 100644 index 000000000..1d587b3b4 --- /dev/null +++ b/documentation/Get-PnPSiteCollectionAppCatalog.md @@ -0,0 +1,84 @@ +--- +Module Name: PnP.PowerShell +title: Get-PnPSiteCollectionAppCatalog +schema: 2.0.0 +applicable: SharePoint Online +external help file: PnP.PowerShell.dll-Help.xml +online version: https://pnp.github.io/powershell/cmdlets/Get-PnPSiteCollectionAppCatalog.html +--- + +# Get-PnPSiteCollectionAppCatalog + +## SYNOPSIS +Returns all site collection scoped app catalogs that exist on the tenant + +## SYNTAX + +```powershell +Get-PnPSiteCollectionAppCatalog [-ExcludeDeletedSites ] [-Connection ] [-Verbose] [] +``` + +## DESCRIPTION +Returns all the site collection scoped app catalogs that exist on the tenant + +## EXAMPLES + +### EXAMPLE 1 +```powershell +Get-PnPSiteCollectionAppCatalog +``` +Will return all the site collection app catalogs that exist on the tenant, including those that may be in the tenant recycle bin + +### EXAMPLE 2 +```powershell +Get-PnPSiteCollectionAppCatalog -ExcludeDeletedSites +``` +Will return all the site collection app catalogs that exist on the tenant excluding the site collections having App Catalogs that are in the tenant recycle bin + +## PARAMETERS + +### -ExcludeDeletedSites +When provided, all site collections having site collection App Catalogs but residing in the tenant recycle bin, will be excluded + +```yaml +Type: SwitchParameter +Parameter Sets: (All) + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Connection +Optional connection to be used by the cmdlet. Retrieve the value for this parameter by either specifying -ReturnConnection on Connect-PnPOnline or by executing Get-PnPConnection. + +```yaml +Type: PnPConnection +Parameter Sets: (All) + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -Verbose +When provided, additional debug statements will be shown while executing the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +## RELATED LINKS + +[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) \ No newline at end of file diff --git a/documentation/Get-PnPSiteCollectionAppCatalogs.md b/documentation/Get-PnPSiteCollectionAppCatalogs.md deleted file mode 100644 index 0b011f4af..000000000 --- a/documentation/Get-PnPSiteCollectionAppCatalogs.md +++ /dev/null @@ -1,38 +0,0 @@ ---- -Module Name: PnP.PowerShell -title: Get-PnPSiteCollectionAppCatalogs -schema: 2.0.0 -applicable: SharePoint Online -external help file: PnP.PowerShell.dll-Help.xml -online version: https://pnp.github.io/powershell/cmdlets/Get-PnPSiteCollectionAppCatalogs.html ---- - -# Get-PnPSiteCollectionAppCatalogs - -## SYNOPSIS -Returns site collection scoped app catalogs - -## SYNTAX - -```powershell -Get-PnPSiteCollectionAppCatalogs - [] -``` - -## DESCRIPTION -Returns site collection scoped app catalogs - -## EXAMPLES - -### EXAMPLE 1 -```powershell -Get-PnPSiteCollectionAppCatalogs -``` -Will return the site collection app catalogs - -## PARAMETERS - -## RELATED LINKS - -[Microsoft 365 Patterns and Practices](https://aka.ms/m365pnp) - diff --git a/src/Commands/Admin/GetSiteCollectionAppCatalog.cs b/src/Commands/Admin/GetSiteCollectionAppCatalog.cs new file mode 100644 index 000000000..60ef9ae89 --- /dev/null +++ b/src/Commands/Admin/GetSiteCollectionAppCatalog.cs @@ -0,0 +1,69 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Management.Automation; +using Microsoft.SharePoint.Client; +using PnP.PowerShell.Commands.Attributes; +using PnP.PowerShell.Commands.Base; +using PnP.PowerShell.Commands.Model.SharePoint; + +namespace PnP.PowerShell.Commands +{ + [Cmdlet(VerbsCommon.Get, "PnPSiteCollectionAppCatalog")] + [Alias("Get-PnPSiteCollectionAppCatalogs")] + [WriteAliasWarning("Please use 'Get-PnPSiteCollectionAppCatalog' (singular). The alias 'Get-PnPSiteCollectionAppCatalogs' (plural) will be removed in a future release.")] + [OutputType(typeof(IEnumerable))] + public class GetSiteCollectionAppCatalog : PnPAdminCmdlet + { + [Parameter(Mandatory = false)] + public SwitchParameter ExcludeDeletedSites; + + protected override void ExecuteCmdlet() + { + WriteVerbose("Retrieving all site collection App Catalogs from SharePoint Online"); + + var appCatalogsCsom = ClientContext.Web.TenantAppCatalog.SiteCollectionAppCatalogsSites; + ClientContext.Load(appCatalogsCsom); + ClientContext.ExecuteQueryRetry(); + + var appCatalogsLocalModel = appCatalogsCsom.Select(ac => + new SiteCollectionAppCatalog { + AbsoluteUrl = ac.AbsoluteUrl, + ErrorMessage = ac.ErrorMessage, + SiteID = ac.SiteID + } + ).ToArray(); + + WriteVerbose($"{appCatalogsLocalModel.Length} site collection App Catalog{(appCatalogsLocalModel.Length != 1 ? "s have" : " has")} been retrieved"); + + var results = new List(appCatalogsLocalModel.Length); + foreach (var appCatalogLocalModel in appCatalogsLocalModel) + { + if (appCatalogLocalModel.SiteID.HasValue) + { + try + { + WriteVerbose($"Validating site collection App Catalog at {appCatalogLocalModel.AbsoluteUrl}"); + + appCatalogLocalModel.AbsoluteUrl = Tenant.GetSitePropertiesById(appCatalogLocalModel.SiteID.Value, false).Url; + results.Add(appCatalogLocalModel); + } + catch (Microsoft.SharePoint.Client.ServerException e) when (e.ServerErrorTypeName.Equals("Microsoft.Online.SharePoint.Common.SpoNoSiteException", StringComparison.InvariantCultureIgnoreCase)) + { + if(!ExcludeDeletedSites.ToBool()) + { + WriteVerbose($"Site collection App Catalog at {appCatalogLocalModel.AbsoluteUrl} regards a site that has been deleted"); + results.Add(appCatalogLocalModel); + } + else + { + WriteVerbose($"Site collection App Catalog at {appCatalogLocalModel.AbsoluteUrl} regards a site that has been deleted. Since the {nameof(ExcludeDeletedSites)} flag has been provided, it will not be included in the results."); + } + } + } + } + + WriteObject(results, true); + } + } +} \ No newline at end of file diff --git a/src/Commands/Admin/GetSiteCollectionAppCatalogs.cs b/src/Commands/Admin/GetSiteCollectionAppCatalogs.cs deleted file mode 100644 index 4bcf98b89..000000000 --- a/src/Commands/Admin/GetSiteCollectionAppCatalogs.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Management.Automation; -using Microsoft.SharePoint.Client; - - -namespace PnP.PowerShell.Commands -{ - [Cmdlet(VerbsCommon.Get, "PnPSiteCollectionAppCatalogs")] - public class GetSiteCollectionAppCatalogs : PnPWebCmdlet - { - protected override void ExecuteCmdlet() - { - var allowedSites = this.CurrentWeb.TenantAppCatalog.SiteCollectionAppCatalogsSites; - ClientContext.Load(allowedSites); - ClientContext.ExecuteQueryRetry(); - - WriteObject(allowedSites, true); - } - } -} \ No newline at end of file diff --git a/src/Commands/Admin/GetTenantSite.cs b/src/Commands/Admin/GetTenantSite.cs index 668cef586..56b6f8401 100644 --- a/src/Commands/Admin/GetTenantSite.cs +++ b/src/Commands/Admin/GetTenantSite.cs @@ -4,7 +4,6 @@ using Microsoft.Online.SharePoint.TenantAdministration; using Microsoft.SharePoint.Client; using PnP.PowerShell.Commands.Base; -using PnP.PowerShell.Commands.Enums; using System.Collections.Generic; using Microsoft.Online.SharePoint.TenantManagement; using PnP.PowerShell.Commands.Base.PipeBinds; diff --git a/src/Commands/Model/SharePoint/SiteCollectionAppCatalog.cs b/src/Commands/Model/SharePoint/SiteCollectionAppCatalog.cs new file mode 100644 index 000000000..2f572f01a --- /dev/null +++ b/src/Commands/Model/SharePoint/SiteCollectionAppCatalog.cs @@ -0,0 +1,26 @@ +using System; + +namespace PnP.PowerShell.Commands.Model.SharePoint +{ + /// + /// All properties regarding a site collection scoped App Catalog + /// + public class SiteCollectionAppCatalog + { + /// + /// The full Url to the location of the App Catalog in the tenant + /// + public string AbsoluteUrl { get; set; } + + /// + /// Informational message regarding the provisioning of the App Catalog + /// + public string ErrorMessage { get; set; } + + /// + /// Unique identifier of the site on which this App Catalog is located + /// + public Guid? SiteID { get; set; } + + } +} \ No newline at end of file From ad89e82c138284a292f41c97c9d3183a76df85bf Mon Sep 17 00:00:00 2001 From: = <=> Date: Tue, 28 Jun 2022 11:12:38 +0200 Subject: [PATCH 2/2] Added additional CurrentSite parameter --- CHANGELOG.md | 7 ++--- .../Get-PnPSiteCollectionAppCatalog.md | 22 ++++++++++++++- .../Admin/GetSiteCollectionAppCatalog.cs | 27 ++++++++++++++++--- 3 files changed, 49 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b8e52522..e32d59d75 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -63,7 +63,8 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Added `Get-Microsoft365GroupYammerCommunity` cmdlet to retrieve details on the Yammer Community connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) - Added `Get-Microsoft365GroupTeam` cmdlet to retrieve details on the Microsoft Teams team connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) - Added `Get-Microsoft365GroupEndpoints` cmdlet to retrieve details on all endpoints connected to a Microsoft 365 Group [#2038](https://github.com/pnp/powershell/pull/2038) -- Added `-ExcludeDeletedSites` optional parameter to `Get-PnPSiteCollectionAppCatalogs` which allows for site collections with App Catalogs that are in the recycle bin to be exluded from the results +- Added `-ExcludeDeletedSites` optional parameter to `Get-PnPSiteCollectionAppCatalogs` which allows for site collections with App Catalogs that are in the recycle bin to be exluded from the results [#2044](https://github.com/pnp/powershell/pull/2044) +- Added `-CurrentSite` optional parameter to `Get-PnPSiteCollectionAppCatalogs` which allows for checking if the currently connected to site has a site collection App Catalogs provisioned on it [#2044](https://github.com/pnp/powershell/pull/2044) ### Changed @@ -81,7 +82,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Changed that almost every cmdlet now supports passing in a specific connection using `-Connection`. If omitted, the default connection will be used. [#1949](https://github.com/pnp/powershell/pull/1949), [#2011](https://github.com/pnp/powershell/pull/2011), [#1958](https://github.com/pnp/powershell/pull/1958) - Changed connecting with `Connect-PnPOnline -Credentials` now throwing a clear exception when making a typo in the hostname instead of getting stuck [#686](https://github.com/pnp/pnpframework/pull/686) - Changed `Get-PnPHubSiteChild` to have its `-Identity` parameter become optional. If not provided, the currently connected to site will be used. [#2033](https://github.com/pnp/powershell/pull/2033) -- Changed `Get-PnPSiteCollectionAppCatalogs` (plural) to `Get-PnPSiteCollectionAppCatalog` (singular) to follow the naming convention +- Changed `Get-PnPSiteCollectionAppCatalogs` (plural) to `Get-PnPSiteCollectionAppCatalog` (singular) to follow the naming convention [#2044](https://github.com/pnp/powershell/pull/2044) ### Fixed @@ -114,7 +115,7 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). - Fixed `Get-PnPHubSiteChild` throwing an exception when passing in a URL that is actually not a hub site [#2033](https://github.com/pnp/powershell/pull/2033) - Fixed `Add-PnPListItem` not showing field name when it has an improper value assigned to it [#2002](https://github.com/pnp/powershell/pull/2002) - Fixed connecting using `Connect-PnPOnline -Interactive -ClientId` not working well when already having an App-Only connection using the same ClientId [#2035](https://github.com/pnp/powershell/pull/2035) -- Fixed `Get-PnPSiteCollectionAppCatalog` not returning updated site collection URLs if they had been renamed +- Fixed `Get-PnPSiteCollectionAppCatalog` not returning updated site collection URLs if they had been renamed [#2044](https://github.com/pnp/powershell/pull/2044) ### Removed diff --git a/documentation/Get-PnPSiteCollectionAppCatalog.md b/documentation/Get-PnPSiteCollectionAppCatalog.md index 1d587b3b4..6e83220b6 100644 --- a/documentation/Get-PnPSiteCollectionAppCatalog.md +++ b/documentation/Get-PnPSiteCollectionAppCatalog.md @@ -15,7 +15,7 @@ Returns all site collection scoped app catalogs that exist on the tenant ## SYNTAX ```powershell -Get-PnPSiteCollectionAppCatalog [-ExcludeDeletedSites ] [-Connection ] [-Verbose] [] +Get-PnPSiteCollectionAppCatalog [-CurrentSite ] [-ExcludeDeletedSites ] [-Connection ] [-Verbose] [] ``` ## DESCRIPTION @@ -29,6 +29,12 @@ Get-PnPSiteCollectionAppCatalog ``` Will return all the site collection app catalogs that exist on the tenant, including those that may be in the tenant recycle bin +### EXAMPLE 2 +```powershell +Get-PnPSiteCollectionAppCatalog -CurrentSite +``` +Will return the site collection app catalog for the currently connected to site, if it has one. Otherwise it will yield no result. + ### EXAMPLE 2 ```powershell Get-PnPSiteCollectionAppCatalog -ExcludeDeletedSites @@ -37,6 +43,20 @@ Will return all the site collection app catalogs that exist on the tenant exclud ## PARAMETERS +### -CurrentSite +When provided, it will check if the currently connected to site has a site collection App Catalog and will return information on it. If the current site holds no site collection App Catalog, an empty response will be returned. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -ExcludeDeletedSites When provided, all site collections having site collection App Catalogs but residing in the tenant recycle bin, will be excluded diff --git a/src/Commands/Admin/GetSiteCollectionAppCatalog.cs b/src/Commands/Admin/GetSiteCollectionAppCatalog.cs index 60ef9ae89..ede1383d2 100644 --- a/src/Commands/Admin/GetSiteCollectionAppCatalog.cs +++ b/src/Commands/Admin/GetSiteCollectionAppCatalog.cs @@ -18,6 +18,9 @@ public class GetSiteCollectionAppCatalog : PnPAdminCmdlet [Parameter(Mandatory = false)] public SwitchParameter ExcludeDeletedSites; + [Parameter(Mandatory = false)] + public SwitchParameter CurrentSite; + protected override void ExecuteCmdlet() { WriteVerbose("Retrieving all site collection App Catalogs from SharePoint Online"); @@ -32,11 +35,29 @@ protected override void ExecuteCmdlet() ErrorMessage = ac.ErrorMessage, SiteID = ac.SiteID } - ).ToArray(); + ).ToList(); + + WriteVerbose($"{appCatalogsLocalModel.Count} site collection App Catalog{(appCatalogsLocalModel.Count != 1 ? "s have" : " has")} been retrieved"); + + if(CurrentSite.ToBool()) + { + SiteContext.Site.EnsureProperties(s => s.Id); + + WriteVerbose($"Filtering down to only the current site at {Connection.Url} with ID {SiteContext.Site.Id}"); + var currentSite = appCatalogsLocalModel.FirstOrDefault(a => a.SiteID.HasValue && a.SiteID.Value == SiteContext.Site.Id); - WriteVerbose($"{appCatalogsLocalModel.Length} site collection App Catalog{(appCatalogsLocalModel.Length != 1 ? "s have" : " has")} been retrieved"); + appCatalogsLocalModel.Clear(); + + if(currentSite == null) + { + WriteVerbose($"Current site at {Connection.Url} with ID {SiteContext.Site.Id} does not have a site collection App Catalog on it"); + return; + } + + appCatalogsLocalModel.Add(currentSite); + } - var results = new List(appCatalogsLocalModel.Length); + var results = new List(appCatalogsLocalModel.Count); foreach (var appCatalogLocalModel in appCatalogsLocalModel) { if (appCatalogLocalModel.SiteID.HasValue)