public/Set-odscShortcutState.ps1
|
function Set-odscShortcutState { [CmdletBinding(DefaultParameterSetName = 'UserPrincipalName', SupportsShouldProcess)] param( [Parameter(Mandatory = $true, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $true, ParameterSetName = 'UserObjectId')] [string] $Uri, [Parameter(Mandatory = $false, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $false, ParameterSetName = 'UserObjectId')] [string] $DocumentLibrary, [Parameter(Mandatory = $false, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $false, ParameterSetName = 'UserObjectId')] [string] $DocumentLibraryId, [Parameter(Mandatory = $false, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $false, ParameterSetName = 'UserObjectId')] [string] $FolderPath, [Parameter(Mandatory = $false, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $false, ParameterSetName = 'UserObjectId')] [string] $RelativePath, [Parameter(Mandatory = $false, ParameterSetName = 'UserPrincipalName')] [Parameter(Mandatory = $false, ParameterSetName = 'UserObjectId')] [string] $ShortcutName, [Parameter(Mandatory = $true, ParameterSetName = 'UserPrincipalName', ValueFromPipelineByPropertyName = $true)] [string] $UserPrincipalName, [Parameter(Mandatory = $true, ParameterSetName = 'UserObjectId', ValueFromPipelineByPropertyName = $true)] [Alias('UserId')] [string] $UserObjectId, [Parameter(Mandatory = $false)] [ValidateSet('Present', 'Absent')] [string] $State = 'Present', [Parameter(Mandatory = $false)] [ValidateSet('Skip', 'Replace', 'Rename', 'Error')] [string] $ConflictAction = 'Skip', [Parameter(Mandatory = $false)] [switch] $PassThru ) process { try { if (-not $DocumentLibrary -and -not $DocumentLibraryId) { Write-Error 'Specify -DocumentLibrary or -DocumentLibraryId.' -ErrorAction Stop } $User = switch ($PsCmdlet.ParameterSetName) { 'UserPrincipalName' { $UserPrincipalName } 'UserObjectId' { $UserObjectId } } $Target = Resolve-odscShortcutTarget -Uri $Uri -DocumentLibrary $DocumentLibrary -DocumentLibraryId $DocumentLibraryId -FolderPath $FolderPath if (-not $ShortcutName) { $ShortcutName = $Target.DefaultShortcutName } $ResultParameters = @{ User = $User TargetSite = $Uri TargetLibrary = if ($DocumentLibrary) { $DocumentLibrary } else { $Target.DocumentLibraryName } TargetFolderPath = $FolderPath } $ShortcutResource = Join-odscDrivePathResource -User $User -RelativePath $RelativePath -Name $ShortcutName $ExistingShortcut = $null try { $ExistingShortcut = Invoke-odscApiRequest -Resource $ShortcutResource -Method ([Microsoft.PowerShell.Commands.WebRequestMethod]::Get) -ErrorAction Stop } catch { $StatusCode = Get-odscGraphStatusCode -ErrorRecord $_ if ($StatusCode -eq 404) { $ExistingShortcut = $null } elseif ($StatusCode -eq 403) { Write-Error "Unable to check for existing shortcut '$ShortcutName' for '$User'. Microsoft Graph returned 403 for $ShortcutResource. Verify permission to read the user's OneDrive." -ErrorAction Stop } else { Write-Error "Unable to check for existing shortcut '$ShortcutName' for '$User'. $($_.Exception.Message)" -ErrorAction Stop } } $MatchesTarget = $ExistingShortcut -and (Test-odscShortcutTargetMatch -Shortcut $ExistingShortcut -Target $Target) if ($State -eq 'Absent') { if (-not $ExistingShortcut) { return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'Remove' -Status 'AlreadyAbsent' -Message 'Shortcut was already absent.' } if (-not $ExistingShortcut.remoteItem) { Write-Error "Existing item '$ShortcutName' for '$User' is not a OneDrive shortcut." -ErrorAction Stop } # Only remove the shortcut when it points to the requested target. if (-not $MatchesTarget) { return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'None' -Status 'SkippedConflict' -Response $ExistingShortcut -Message 'A shortcut with the requested name exists but points to a different target. It was not removed.' } if ($PSCmdlet.ShouldProcess("${User}'s OneDrive", "Removing shortcut '$ShortcutName'")) { Invoke-odscApiRequest -Resource $ShortcutResource -Method ([Microsoft.PowerShell.Commands.WebRequestMethod]::Delete) -ErrorAction Stop | Out-Null return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'Remove' -Status 'Removed' -Response $ExistingShortcut } return } if ($ExistingShortcut) { if ($MatchesTarget) { if ($PassThru) { return $ExistingShortcut } return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'None' -Status 'Compliant' -Response $ExistingShortcut -Message 'Shortcut already points to the requested target.' } switch ($ConflictAction) { 'Skip' { return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'None' -Status 'SkippedConflict' -Response $ExistingShortcut -Message 'An item with the requested shortcut name already exists.' } 'Error' { Write-Error "An item named '$ShortcutName' already exists for '$User' and does not match the requested target." -ErrorAction Stop } 'Replace' { # Never delete a real file or folder, only a shortcut pointing somewhere else. if (-not $ExistingShortcut.remoteItem) { Write-Error "An item named '$ShortcutName' already exists for '$User' and is not a OneDrive shortcut. It will not be replaced." -ErrorAction Stop } if ($PSCmdlet.ShouldProcess("${User}'s OneDrive", "Replacing shortcut '$ShortcutName'")) { Invoke-odscApiRequest -Resource $ShortcutResource -Method ([Microsoft.PowerShell.Commands.WebRequestMethod]::Delete) -ErrorAction Stop | Out-Null } else { return } } 'Rename' { $ShortcutName = "$ShortcutName-$([DateTime]::UtcNow.ToString('yyyyMMddHHmmss'))" } } } if ($PSCmdlet.ShouldProcess("${User}'s OneDrive", "Creating shortcut '$ShortcutName'")) { Resolve-odscOneDriveRoot -User $User | Out-Null $RemoteItem = New-odscRemoteItemReference -Target $Target -ShortcutName $ShortcutName try { $ShortcutResponse = New-odscShortcutItem -User $User -RemoteItem $RemoteItem -ShortcutName $ShortcutName -RelativePath $RelativePath } catch { # The shortcut exists under another name or at the root: report it rather than fail. if ($_.FullyQualifiedErrorId -notlike 'odscShortcutNotRenamed*') { throw } if ($PassThru) { Write-Warning $_.Exception.Message return $_.TargetObject } return Write-odscResult @ResultParameters -ShortcutName $_.TargetObject.name -Action 'Create' -Status 'RenameFailed' -Response $_.TargetObject -Message $_.Exception.Message } if ($PassThru) { return $ShortcutResponse } return Write-odscResult @ResultParameters -ShortcutName $ShortcutName -Action 'Create' -Status 'Created' -Response $ShortcutResponse } } catch { # Non-terminating by default, like the other commands; use -ErrorAction Stop to stop instead. Write-Error $_.Exception.Message } } } |