diff --git a/CHANGELOG.md b/CHANGELOG.md index c8fa03baf..55273b753 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,12 +11,14 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/). ### Added - Added in depth verbose logging to all cmdlets which is revealed by adding `-Verbose` to the cmdlet execution [#4023](https://github.com/pnp/powershell/pull/4023) - Added `-CoreDefaultShareLinkScope` and `-CoreDefaultShareLinkRole` parameters to `Set-PnPTenant` cmdlet. [#4067](https://github.com/pnp/powershell/pull/4067) +- Added `-Identity` parameter to the `Get-PnPFileSharingLink` cmdlet allowing for the retrieval of sharing links based on the file's unique identifier, file instance, listitem instance, or server relative path and supporting retrieval of sharing links for multiple files, such as all in a document library [#4093](https://github.com/pnp/powershell/pull/4093) ### Fixed - `Get-PnPTeamsChannel` and `Get-PnPTeamsPrimaryChannel` returning `unknownFutureValue` as MembershipType instead of `shared` [#4054]https://github.com/pnp/powershell/pull/4054 ### Changed - Fixed `Update-PnPTeamsUser` cmdlet to throw a better error message when after a user is removed from a Team but is still in the connected M365 group, for the few seconds that the 2 are out of sync. [#4068](https://github.com/pnp/powershell/pull/4068) +- Changed `-FileUrl` on `Get-PnPFileSharingLink` to become obsolete. Please switch to using `-Identity` instead, passing in the same value [#4093](https://github.com/pnp/powershell/pull/4093) ### Removed diff --git a/documentation/Get-PnPFileSharingLink.md b/documentation/Get-PnPFileSharingLink.md index f277acc74..02a2c32cf 100644 --- a/documentation/Get-PnPFileSharingLink.md +++ b/documentation/Get-PnPFileSharingLink.md @@ -15,7 +15,7 @@ Retrieves sharing links to associated with the file. ## SYNTAX ```powershell -Get-PnPFileSharingLink -FileUrl [-Connection ] +Get-PnPFileSharingLink -Identity [-Verbose] [-Connection ] ``` ## DESCRIPTION @@ -26,10 +26,52 @@ Retrieves sharing links for a file. ### EXAMPLE 1 ```powershell -Get-PnPFileSharingLink -FileUrl "/sites/demo/Shared Documents/Test.docx" +Get-PnPFileSharingLink -Identity "/sites/demo/Shared Documents/Test.docx" ``` -This will fetch sharing links for `Test.docx` file in the `Shared Documents` library. +This will fetch sharing links for `Test.docx` file in the `Shared Documents` library based on the server relative url. + +### EXAMPLE 2 +```powershell +Get-PnPFileSharingLink -Identity eff4c8ca-7b92-4aa2-9744-855611c6ccf2 +``` + +This will fetch sharing links for the file in the site with the provided unique identifier, regardless of where it is located. + +### EXAMPLE 3 +```powershell +Get-PnPListItem -List "Documents" | Get-PnPFileSharingLink +``` + +This will fetch sharing links for all files in the `Documents` library. + +### EXAMPLE 4 +```powershell +Get-PnPListItem -List "Documents" -Id 1 | Get-PnPFileSharingLink +``` + +This will fetch sharing links for the file in the `Documents` library with Id 1. + +### EXAMPLE 5 +```powershell +Get-PnPFile -Url "/sites/demo/Shared Documents/Test.docx" | Get-PnPFileSharingLink +``` + +This will fetch sharing links for the passed in file. + +### EXAMPLE 6 +```powershell +Get-PnPFileInFolder -Recurse -ExcludeSystemFolders -FolderSiteRelativeUrl "Shared Documents" | Get-PnPFileSharingLink +``` + +This will fetch sharing links for all files in the `Shared Documents` library, including the files in subfolders, excluding the ones in hidden internal system folders. + +### EXAMPLE 7 +```powershell +Get-PnPFileInFolder -Recurse -ExcludeSystemFolders -FolderSiteRelativeUrl "Shared Documents" | Get-PnPFileSharingLink | ? ExpirationDateTime -eq $null +``` + +This will fetch sharing links for all files in the `Shared Documents` library, including the files in subfolders, excluding the ones in hidden internal system folders where no expiration has been set on the sharing of the file. ## PARAMETERS @@ -47,11 +89,11 @@ Accept pipeline input: False Accept wildcard characters: False ``` -### -FileUrl -The file in the site +### -Identity +The server relative path to the file, the unique identifier of the file, the listitem representing the file, or the file object itself to retrieve the sharing links for. ```yaml -Type: String +Type: FilePipeBind Parameter Sets: (All) Required: True @@ -61,6 +103,20 @@ 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) diff --git a/src/Commands/Base/PipeBinds/FilePipeBind.cs b/src/Commands/Base/PipeBinds/FilePipeBind.cs new file mode 100644 index 000000000..572b9ddbe --- /dev/null +++ b/src/Commands/Base/PipeBinds/FilePipeBind.cs @@ -0,0 +1,139 @@ +using System; +using Microsoft.SharePoint.Client; +using System.Management.Automation; +using PnP.Core.Model.SharePoint; +using PnP.Core.Services; + +namespace PnP.PowerShell.Commands.Base.PipeBinds +{ + public sealed class FilePipeBind + { + #region Properties + + public Guid? Id { get; private set; } + public File File { get; private set; } + public IFile CoreFile { get; private set; } + public ListItem ListItem { get; private set; } + public string ServerRelativeUrl { get; private set; } + + #endregion + + #region Constructors + + public FilePipeBind() + { + } + + public FilePipeBind(Guid id) + { + Id = id; + } + + public FilePipeBind(ListItem listItem) + { + ListItem = listItem; + } + + public FilePipeBind(File file) + { + File = file; + } + + public FilePipeBind(IFile coreFile) + { + CoreFile = coreFile; + } + + public FilePipeBind(string id) + { + if (Guid.TryParse(id, out Guid fileGuid)) + { + Id = fileGuid; + } + else + { + ServerRelativeUrl = id; + } + } + + #endregion + + #region Methods + + internal IFile GetCoreFile(PnPContext context, Cmdlet cmdlet = null) + { + if(CoreFile != null) + { + cmdlet?.WriteVerbose("File determined based on CoreFile instance"); + return CoreFile; + } + + if (File != null) + { + cmdlet?.WriteVerbose("File will be retrieved based on CSOM File instance"); + File.EnsureProperties(f => f.UniqueId); + return context.Web.GetFileById(File.UniqueId); + } + + if (ListItem != null) + { + cmdlet?.WriteVerbose("File will be retrieved based on CSOM ListItem instance"); + ListItem.EnsureProperties(i => i.File); + return context.Web.GetFileById(ListItem.File.UniqueId); + } + + if (Id.HasValue) + { + cmdlet?.WriteVerbose("File will be retrieved based on file id"); + return context.Web.GetFileById(Id.Value); + } + + if (!string.IsNullOrEmpty(ServerRelativeUrl)) + { + cmdlet?.WriteVerbose("File will be retrieved based on server relative url"); + return context.Web.GetFileByServerRelativeUrl(ServerRelativeUrl); + } + + throw new PSInvalidOperationException("No information available to retrieve file"); + } + + internal File GetFile(ClientContext context, Cmdlet cmdlet = null) + { + if (File != null) + { + cmdlet?.WriteVerbose("File determined based on CSOM File instance"); + return File; + } + + if (CoreFile != null) + { + cmdlet?.WriteVerbose("File will be retrieved based on PnP Core File instance"); + CoreFile.EnsureProperties(f => f.UniqueId); + return context.Web.GetFileById(File.UniqueId); + } + + if (ListItem != null) + { + cmdlet?.WriteVerbose("File will be retrieved based on CSOM ListItem instance"); + ListItem.EnsureProperties(i => i.File); + return context.Web.GetFileById(ListItem.File.UniqueId); + } + + if (Id.HasValue) + { + cmdlet?.WriteVerbose("File will be retrieved based on file id"); + return context.Web.GetFileById(Id.Value); + } + + if (!string.IsNullOrEmpty(ServerRelativeUrl)) + { + cmdlet?.WriteVerbose("File will be retrieved based on server relative url"); + return context.Web.GetFileByServerRelativeUrl(ServerRelativeUrl); + } + + throw new PSInvalidOperationException("No information available to retrieve file"); + } + + #endregion + } +} \ No newline at end of file diff --git a/src/Commands/Security/GetFileSharingLink.cs b/src/Commands/Security/GetFileSharingLink.cs index 36679342a..fc41946fc 100644 --- a/src/Commands/Security/GetFileSharingLink.cs +++ b/src/Commands/Security/GetFileSharingLink.cs @@ -1,32 +1,54 @@ -using PnP.Framework.Utilities; +using PnP.Core.Model.Security; +using PnP.Core.Model.SharePoint; +using PnP.Framework.Utilities; +using System; using System.Management.Automation; +using PnP.PowerShell.Commands.Base.PipeBinds; namespace PnP.PowerShell.Commands.Security -{ +{ [Cmdlet(VerbsCommon.Get, "PnPFileSharingLink")] + [OutputType(typeof(IGraphPermissionCollection))] public class GetFileSharingLink : PnPWebCmdlet { - [Parameter(Mandatory = true)] + private const string ParameterSet_BYFILEURL = "By file url"; + private const string ParameterSet_BYIDENTITY = "By identity"; + + [Obsolete("Use Identity parameter instead")] + [Parameter(Mandatory = true, ParameterSetName = ParameterSet_BYFILEURL)] public string FileUrl; + [Parameter(Mandatory = true, ValueFromPipeline = true, ParameterSetName = ParameterSet_BYIDENTITY)] + public FilePipeBind Identity; + protected override void ExecuteCmdlet() { - var serverRelativeUrl = string.Empty; - var ctx = Connection.PnPContext; + IFile file; - ctx.Web.EnsureProperties(w => w.ServerRelativeUrl); - - if (!FileUrl.ToLower().StartsWith(ctx.Web.ServerRelativeUrl.ToLower())) + if (ParameterSpecified(nameof(Identity))) { - serverRelativeUrl = UrlUtility.Combine(ctx.Web.ServerRelativeUrl, FileUrl); + file = Identity.GetCoreFile(PnPContext, this); } else { - serverRelativeUrl = FileUrl; - } + var serverRelativeUrl = string.Empty; + var ctx = Connection.PnPContext; - var file = ctx.Web.GetFileByServerRelativeUrl(serverRelativeUrl); + ctx.Web.EnsureProperties(w => w.ServerRelativeUrl); + + if (!FileUrl.ToLower().StartsWith(ctx.Web.ServerRelativeUrl.ToLower())) + { + serverRelativeUrl = UrlUtility.Combine(ctx.Web.ServerRelativeUrl, FileUrl); + } + else + { + serverRelativeUrl = FileUrl; + } + + file = ctx.Web.GetFileByServerRelativeUrl(serverRelativeUrl); + } + WriteVerbose("Retrieving file sharing details from Microsoft Graph"); var sharingLinks = file.GetShareLinks(); WriteObject(sharingLinks?.RequestedItems, true);