diff --git a/.circleci/workflows.yml b/.circleci/workflows.yml index 8e4572fba..fd4ddf8a4 100755 --- a/.circleci/workflows.yml +++ b/.circleci/workflows.yml @@ -45,7 +45,7 @@ parameters: PublishToPSGallery: description: 'When `true` and when run against Master branch, this workflow will publish the latest code to PSGallery' type: boolean - default: false + default: true ManualModuleVersion: description: 'When `true` the pipeline will use the Module Version specified in JumpCloud Module JumpCloud.psd1 file' type: boolean diff --git a/PowerShell/JumpCloud Module/Docs/JumpCloud.md b/PowerShell/JumpCloud Module/Docs/JumpCloud.md index 3611f0ae2..531849ba3 100644 --- a/PowerShell/JumpCloud Module/Docs/JumpCloud.md +++ b/PowerShell/JumpCloud Module/Docs/JumpCloud.md @@ -2,7 +2,7 @@ Module Name: JumpCloud Module Guid: 31c023d1-a901-48c4-90a3-082f91b31646 Download Help Link: https://github.com/TheJumpCloud/support/wiki -Help Version: 1.21.0 +Help Version: 1.22.0 Locale: en-US --- diff --git a/PowerShell/JumpCloud Module/JumpCloud.psd1 b/PowerShell/JumpCloud Module/JumpCloud.psd1 index 358d701d4..4857e343b 100755 --- a/PowerShell/JumpCloud Module/JumpCloud.psd1 +++ b/PowerShell/JumpCloud Module/JumpCloud.psd1 @@ -3,7 +3,7 @@ # # Generated by: JumpCloud Solutions Architect Team # -# Generated on: 5/10/2022 +# Generated on: 5/17/2022 # @{ @@ -12,7 +12,7 @@ RootModule = 'JumpCloud.psm1' # Version number of this module. -ModuleVersion = '1.21.0' +ModuleVersion = '1.22.0' # Supported PSEditions # CompatiblePSEditions = @() diff --git a/PowerShell/JumpCloud Module/Private/NestedFunctions/Get-JCResults.ps1 b/PowerShell/JumpCloud Module/Private/NestedFunctions/Get-JCResults.ps1 index a63b45c44..3207686c8 100644 --- a/PowerShell/JumpCloud Module/Private/NestedFunctions/Get-JCResults.ps1 +++ b/PowerShell/JumpCloud Module/Private/NestedFunctions/Get-JCResults.ps1 @@ -2,7 +2,10 @@ Function Get-JCResults { [CmdletBinding()] Param( - [Parameter(Mandatory = $true, HelpMessage = 'URL of Endpoint')][ValidateNotNullOrEmpty()]$URL + [Parameter(Mandatory = $true, HelpMessage = 'URL of Endpoint')][ValidateNotNullOrEmpty()]$URL, + [Parameter(Mandatory = $true, HelpMessage = 'Method of WebRequest')][ValidateNotNullOrEmpty()]$method, + [Parameter(Mandatory = $true, HelpMessage = 'Limit of WebRequest')][ValidateNotNullOrEmpty()]$limit, + [Parameter(Mandatory = $false, HelpMessage = 'Body of WebRequest, if required')]$body ) begin { $hdrs = @{ @@ -16,7 +19,7 @@ Function Get-JCResults } $resultsArray = @() $totalCount = 1 - $limit = 100 + $limit = [int]$limit $skip = 0 } process { @@ -29,11 +32,16 @@ Function Get-JCResults $passCounter = [math]::ceiling($totalCount/$limit) Write-Debug "number of passes: $passCounter" $resultsArray += $response.Content | ConvertFrom-Json - + for($i = 1; $i -lt $passCounter; $i++) { $skip += $limit $limitURL = $URL + "?limit=$limit&skip=$skip" - $response = Invoke-WebRequest -Method GET -Uri $limitURL -Headers $hdrs -UserAgent:(Get-JCUserAgent) + if ($body){ + $response = Invoke-WebRequest -Method $method -Body $body -Uri $limitURL -Headers $hdrs -UserAgent:(Get-JCUserAgent) + } + else { + $response = Invoke-WebRequest -Method $method -Uri $limitURL -Headers $hdrs -UserAgent:(Get-JCUserAgent) + } $resultsArray += $response.Content | ConvertFrom-Json Write-Debug ("Pass: $i Amount: " + ($response.Content | ConvertFrom-Json).Count) } diff --git a/PowerShell/JumpCloud Module/Public/Groups/SystemGroups/Get-JCSystemGroupMember.ps1 b/PowerShell/JumpCloud Module/Public/Groups/SystemGroups/Get-JCSystemGroupMember.ps1 index ad6b5d491..bad6d0761 100644 --- a/PowerShell/JumpCloud Module/Public/Groups/SystemGroups/Get-JCSystemGroupMember.ps1 +++ b/PowerShell/JumpCloud Module/Public/Groups/SystemGroups/Get-JCSystemGroupMember.ps1 @@ -57,7 +57,7 @@ Function Get-JCSystemGroupMember () Write-Debug "$Group_ID" $limitURL = "{0}/api/v2/Systemgroups/{1}/members" -f $JCUrlBasePath, $Group_ID - $rawResults = Get-JCResults -Url $limitURL + $rawResults = Get-JCResults -Url $limitURL -method "GET" -limit 100 foreach ($uid in $rawResults) { @@ -86,7 +86,7 @@ Function Get-JCSystemGroupMember () { $limitURL = "{0}/api/v2/Systemgroups/{1}/members" -f $JCUrlBasePath, $ByID - $resultsArray = Get-JCResults -Url $limitURL + $resultsArray = Get-JCResults -Url $limitURL -method "GET" -limit 100 } } diff --git a/PowerShell/JumpCloud Module/Public/Groups/UserGroups/Get-JCUserGroupMember.ps1 b/PowerShell/JumpCloud Module/Public/Groups/UserGroups/Get-JCUserGroupMember.ps1 index 3e5d5f724..334c41c8b 100644 --- a/PowerShell/JumpCloud Module/Public/Groups/UserGroups/Get-JCUserGroupMember.ps1 +++ b/PowerShell/JumpCloud Module/Public/Groups/UserGroups/Get-JCUserGroupMember.ps1 @@ -52,7 +52,7 @@ Function Get-JCUserGroupMember () $limitURL = "{0}/api/v2/usergroups/{1}/members" -f $JCUrlBasePath, $Group_ID Write-Debug $limitURL - $rawResults = Get-JCResults -Url $limitURL + $rawResults = Get-JCResults -Url $limitURL -method "GET" -limit 100 foreach ($uid in $rawResults) { @@ -82,7 +82,7 @@ Function Get-JCUserGroupMember () { $limitURL = "{0}/api/v2/usergroups/{1}/members" -f $JCUrlBasePath, $ByID Write-Debug $limitURL - $resultsArray = Get-JCResults -Url $limitURL + $resultsArray = Get-JCResults -Url $limitURL -method "GET" -limit 100 } } diff --git a/PowerShell/JumpCloud Module/Public/Users/Get-JCUser.ps1 b/PowerShell/JumpCloud Module/Public/Users/Get-JCUser.ps1 index 402b8155e..4e8f8c8b0 100644 --- a/PowerShell/JumpCloud Module/Public/Users/Get-JCUser.ps1 +++ b/PowerShell/JumpCloud Module/Public/Users/Get-JCUser.ps1 @@ -117,7 +117,7 @@ Function Get-JCUser () [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'SearchFilter', HelpMessage = 'The managedAppleId of the JumpCloud user you wish to search for.')] [String]$managedAppleId, - [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'SearchFilter', HelpMessage = 'The manager username or ID of the JumpCloud user you wish to search for.')] + [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'SearchFilter', HelpMessage = 'The manager username, primary email or ID of the JumpCloud user you wish to search for.')] [String]$manager, [Parameter(ValueFromPipelineByPropertyName, ParameterSetName = 'SearchFilter', HelpMessage = 'A search filter to return users that are in an ACTIVATED, STAGED or SUSPENDED state')] @@ -314,22 +314,20 @@ Function Get-JCUser () if (((Select-String -InputObject $param.Value -Pattern $regexPattern).Matches.value)::IsNullOrEmpty){ # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) # Set managerValue; this is a validated user id $managerValue = $managerResults.id - # if no value was returned, then assume the case this is actually a username and search + # if no value was returned, then assume the case this is actually a username and search if (!$managerValue){ $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -337,13 +335,37 @@ Function Get-JCUser () $managerValue = $managerResults.id } } - else { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + # Search manager using email + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) diff --git a/PowerShell/JumpCloud Module/Public/Users/New-JCUser.ps1 b/PowerShell/JumpCloud Module/Public/Users/New-JCUser.ps1 index 95b5af8a4..90e717290 100755 --- a/PowerShell/JumpCloud Module/Public/Users/New-JCUser.ps1 +++ b/PowerShell/JumpCloud Module/Public/Users/New-JCUser.ps1 @@ -150,7 +150,7 @@ Function New-JCUser () [string] $state, - [Parameter(ValueFromPipelineByPropertyName = $True, HelpMessage = 'The manager username or ID of the JumpCloud manager user; must be a valid user')] + [Parameter(ValueFromPipelineByPropertyName = $True, HelpMessage = 'The manager username, ID or primary email of the JumpCloud manager user; must be a valid user')] [string]$manager, [Parameter(ValueFromPipelineByPropertyName = $True, HelpMessage = 'The managedAppleId for the user')] @@ -326,10 +326,9 @@ Function New-JCUser () if (((Select-String -InputObject $param.Value -Pattern $regexPattern).Matches.value)::IsNullOrEmpty){ # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -338,10 +337,9 @@ Function New-JCUser () # if no value was returned, then assume the case this is actuallty a username and search if (!$managerValue){ $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -349,13 +347,37 @@ Function New-JCUser () $managerValue = $managerResults.id } } - else { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + # if no value was returned, then assume the case this is actuallty a username and search + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) diff --git a/PowerShell/JumpCloud Module/Public/Users/Set-JCUser.ps1 b/PowerShell/JumpCloud Module/Public/Users/Set-JCUser.ps1 index 7cea49152..c47cb0cb0 100644 --- a/PowerShell/JumpCloud Module/Public/Users/Set-JCUser.ps1 +++ b/PowerShell/JumpCloud Module/Public/Users/Set-JCUser.ps1 @@ -239,7 +239,7 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline [nullable[bool]] $suspended, - [Parameter(ValueFromPipelineByPropertyName = $true, HelpMessage = 'The manager username or ID of the JumpCloud manager user; must be a valid user')] + [Parameter(ValueFromPipelineByPropertyName = $true, HelpMessage = 'The manager username, ID or primary email of the JumpCloud manager user; must be a valid user')] [string] $manager, @@ -606,22 +606,20 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline if (((Select-String -InputObject $param.Value -Pattern $regexPattern).Matches.value)::IsNullOrEmpty){ # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) # Set managerValue; this is a validated user id $managerValue = $managerResults.id - # if no value was returned, then assume the case this is actuallty a username and search + # if no value was returned, then assume the case this is actually a username and search if (!$managerValue){ $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -629,13 +627,38 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline $managerValue = $managerResults.id } } - else { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + # Search for manager using email + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + # if no value was returned, then assume the case this is actually a username and search + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -747,10 +770,9 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline { # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -760,10 +782,9 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline if (!$managerValue) { $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -771,14 +792,38 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline $managerValue = $managerResults.id } } - else - { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + # Search for manager using email + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + # if no value was returned, then assume the case this is actually a username and search + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -971,23 +1016,21 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline { # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) # Set managerValue; this is a validated user id $managerValue = $managerResults.id - # if no value was returned, then assume the case this is actuallty a username and search + # if no value was returned, then assume the case this is actually a username and search if (!$managerValue) { $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -995,14 +1038,39 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline $managerValue = $managerResults.id } } - else - { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + Write-Debug "This is true" + # Search for manager using email + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + # if no value was returned, then assume the case this is actually a username and search + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -1141,22 +1209,20 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline if (((Select-String -InputObject $param.Value -Pattern $regexPattern).Matches.value)::IsNullOrEmpty){ # if we have a 24 characterid, try to match the id using the search endpoint $managerSearch = @{ - filter = @{ - or = @( - '_id:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('id') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) # Set managerValue; this is a validated user id $managerValue = $managerResults.id - # if no value was returned, then assume the case this is actuallty a username and search + # if no value was returned, then assume the case this is actually a username and search if (!$managerValue){ $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) @@ -1164,13 +1230,39 @@ UserID has an Alias of _id. This means you can leverage the PowerShell pipeline $managerValue = $managerResults.id } } - else { + # Use class mailaddress to check if $param.value is email + try { + $null = [mailaddress]$EmailAddress + Write-Debug "This is true" + # Search for manager using email + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('email') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue; this is a validated user id + $managerValue = $managerResults.id + # if no value was returned, then assume the case this is actually a username and search + if (!$managerValue){ + $managerSearch = @{ + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') + } + } + $managerResults = Search-JcSdkUser -Body:($managerSearch) + # Set managerValue from the matched username + $managerValue = $managerResults.id + } + } + catch { # search the username in the search endpoint $managerSearch = @{ - filter = @{ - or = @( - 'username:$eq:' + $param.Value - ) + searchFilter = @{ + searchTerm = @($param.Value) + fields = @('username') } } $managerResults = Search-JcSdkUser -Body:($managerSearch) diff --git a/PowerShell/JumpCloud Module/Public/Utilities/Backup-JCOrganization.ps1 b/PowerShell/JumpCloud Module/Public/Utilities/Backup-JCOrganization.ps1 index d45fd2dbe..4d000d17f 100644 --- a/PowerShell/JumpCloud Module/Public/Utilities/Backup-JCOrganization.ps1 +++ b/PowerShell/JumpCloud Module/Public/Utilities/Backup-JCOrganization.ps1 @@ -220,7 +220,7 @@ Function Backup-JCOrganization $AssociationBaseName = "Association-{0}To{1}" -f $SourceTypeMap.Key, $TargetTypeMap.Key $AssociationFileName = "{0}.{1}" -f $AssociationBaseName, $Format $AssociationFullName = "{0}/{1}" -f $TempPath, $AssociationFileName - $AssociationJobs += Start-Job -ScriptBlock:( { Param ($SourceTypeMap, $TargetTypeMap, $BackupFile, $AssociationBaseName, $AssociationFileName, $AssociationFullName, $Format, $Debug); + $AssociationJobs += Start-Job -ScriptBlock:( { Param ($SourceTypeMap, $TargetTypeMap, $BackupFile, $AssociationBaseName, $AssociationFileName, $AssociationFullName, $Format, $Settings, $Debug); $AssociationResults = @() # Get content from the file $BackupRecords = If ($Format -eq 'json') @@ -288,6 +288,78 @@ Function Backup-JCOrganization $AssociationResults += $AssociationResult } } + ElseIf (($SourceTypeMap.Value.Name -eq 'command' -and $TargetTypeMap.Value.Name -eq 'system' -and $Settings.ROLE -eq 'Read Only') -or ($SourceTypeMap.Value.Name -eq 'command' -and $TargetTypeMap.Value.Name -eq 'system_group' -and $Settings.ROLE -eq 'Read Only')) + { + # Note on SA-2014 read only cases, this is temporary and should be addressed in the API but this is proving difficult, these cases are only necessary since the association endpoints on systems->commands/softwareapps is disabled for readonly users + $Command = 'Get-JcSdk{0}Traverse{2} -{0}Id:("{1}")' -f $SourceTypeMap.Key, $BackupRecord.id, (Get-Culture).TextInfo.ToTitleCase($TargetTypeMap.Value.Name) + If ($PSBoundParameters.Debug) { Write-Host ("DEBUG: Running: $Command") -ForegroundColor:('Yellow') } + $AssociationResult = Invoke-Expression -Command:($Command) + If (-not [System.String]::IsNullOrEmpty($AssociationResult)) + { + # The direct association/"Get-JcSdk*Membership" endpoints return null for FromId. So manually populate them here. + $AssociationResult.Paths | ForEach-Object { + $_ | ForEach-Object { + if ($_.FromType -eq $SourceTypeMap.Value.Name -and $_.ToType -eq $TargetTypeMap.Value.Name){ + $AssociationResults += $_ + } + } + } + } + } + ElseIf (($SourceTypeMap.Value.Name -eq 'system' -and $TargetTypeMap.Value.Name -eq 'command' -and $Global:JCSettings.ROLE -eq 'Read Only') -or ($SourceTypeMap.Value.Name -eq 'system_group' -and $TargetTypeMap.Value.Name -eq 'command' -and $Global:JCSettings.ROLE -eq 'Read Only')) + { + $Command = 'Get-JcSdk{0}Traverse{2} -{0}Id:("{1}")' -f $SourceTypeMap.Key, $BackupRecord.id, (Get-Culture).TextInfo.ToTitleCase($TargetTypeMap.Value.Name) + If ($PSBoundParameters.Debug) { Write-Host ("DEBUG: Running: $Command") -ForegroundColor:('Yellow') } + $AssociationResult = Invoke-Expression -Command:($Command) + If (-not [System.String]::IsNullOrEmpty($AssociationResult)) + { + # The direct association/"Get-JcSdk*Membership" endpoints return null for FromId. So manually populate them here. + $AssociationResult.Paths | ForEach-Object { + $_ | ForEach-Object { + if ($_.FromType -eq $SourceTypeMap.Value.Name -and $_.ToType -eq $TargetTypeMap.Value.Name) + { + $AssociationResults += $_ + } + } + } + } + } + ElseIf (($SourceTypeMap.Value.Name -eq 'SoftwareApp' -and $TargetTypeMap.Value.Name -eq 'system' -and $Global:JCSettings.ROLE -eq 'Read Only') -or ($SourceTypeMap.Value.Name -eq 'SoftwareApp' -and $TargetTypeMap.Value.Name -eq 'system_group' -and $Global:JCSettings.ROLE -eq 'Read Only')) + { + $Command = 'Get-JcSdk{0}Traverse{2} -{0}Id:("{1}")' -f $SourceTypeMap.Key, $BackupRecord.id, (Get-Culture).TextInfo.ToTitleCase($TargetTypeMap.Value.Name) + If ($PSBoundParameters.Debug) { Write-Host ("DEBUG: Running: $Command") -ForegroundColor:('Yellow') } + $AssociationResult = Invoke-Expression -Command:($Command) + If (-not [System.String]::IsNullOrEmpty($AssociationResult)) + { + # The direct association/"Get-JcSdk*Membership" endpoints return null for FromId. So manually populate them here. + $AssociationResult.Paths | ForEach-Object { + $_ | ForEach-Object { + if ($_.FromType -eq $SourceTypeMap.Value.Name -and $_.ToType -eq $TargetTypeMap.Value.Name) + { + $AssociationResults += $_ + } + } + } + } + } + ElseIf (($SourceTypeMap.Value.Name -eq 'system' -and $TargetTypeMap.Value.Name -eq 'SoftwareApp' -and $Global:JCSettings.ROLE -eq 'Read Only') -or ($SourceTypeMap.Value.Name -eq 'system_group' -and $TargetTypeMap.Value.Name -eq 'SoftwareApp' -and $Global:JCSettings.ROLE -eq 'Read Only')) + { + $Command = 'Get-JcSdk{0}Traverse{2} -{0}Id:("{1}")' -f $SourceTypeMap.Key, $BackupRecord.id, (Get-Culture).TextInfo.ToTitleCase($TargetTypeMap.Value.Name) + If ($PSBoundParameters.Debug) { Write-Host ("DEBUG: Running: $Command") -ForegroundColor:('Yellow') } + $AssociationResult = Invoke-Expression -Command:($Command) + If (-not [System.String]::IsNullOrEmpty($AssociationResult)) + { + # The direct association/"Get-JcSdk*Membership" endpoints return null for FromId. So manually populate them here. + $AssociationResult.Paths | ForEach-Object { + $_ | ForEach-Object { + if ($_.FromType -eq $SourceTypeMap.Value.Name -and $_.ToType -eq $TargetTypeMap.Value.Name) + { + $AssociationResults += $_ + } + } + } + } + } Else { $Command = 'Get-JcSdk{0}Association -{1}Id:("{2}") -Targets:("{3}")' -f $SourceTypeMap.Key, $SourceTypeMap.Key.Replace('UserGroup', 'Group').Replace('SystemGroup', 'Group'), $BackupRecord.id, $TargetTypeMap.Value.Name @@ -342,7 +414,7 @@ Function Backup-JCOrganization # Build hash to return data Return @{$AssociationBaseName = $AssociationResults } } - }) -ArgumentList:($SourceTypeMap, $TargetTypeMap, $BackupFile, $AssociationBaseName, $AssociationFileName, $AssociationFullName, $Format, $PSBoundParameters.Debug) + }) -ArgumentList:($SourceTypeMap, $TargetTypeMap, $BackupFile, $AssociationBaseName, $AssociationFileName, $AssociationFullName, $Format, $global:JCSettings, $PSBoundParameters.Debug) } } } diff --git a/PowerShell/JumpCloud Module/Tests/Public/Users/Get-JCUser.tests.ps1 b/PowerShell/JumpCloud Module/Tests/Public/Users/Get-JCUser.tests.ps1 index dc24b044e..3707ee602 100755 --- a/PowerShell/JumpCloud Module/Tests/Public/Users/Get-JCUser.tests.ps1 +++ b/PowerShell/JumpCloud Module/Tests/Public/Users/Get-JCUser.tests.ps1 @@ -94,6 +94,14 @@ Describe -Tag:('JCUser') 'Get-JCUser 1.1' { $NewUser.manager | Should -Be $managerId Remove-JCUser -UserID $NewUser._id -force } + It "Searches a JumpCloud user by managerEmail" { + $managerEmail = $PesterParams_User1.email + $managerId = $PesterParams_User1.id + $NewUser = New-RandomUser -Domain DeleteMe | New-JCUser -manager $managerEmail + $NewUser = Get-JCUser -manager $managerEmail + $NewUser.manager | Should -Be $managerId + Remove-JCUser -UserID $NewUser._id -force + } It "Searches a JumpCloud user by state SUSPENDED" { $NewUser = New-RandomUser -Domain DeleteMe | New-JcUser -state "SUSPENDED" $SearchUser = Get-JCUser -state "SUSPENDED" | Select-Object -First 1 diff --git a/PowerShell/JumpCloud Module/Tests/Public/Users/New-JCUser.tests.ps1 b/PowerShell/JumpCloud Module/Tests/Public/Users/New-JCUser.tests.ps1 index eec086b62..d1b9802b5 100755 --- a/PowerShell/JumpCloud Module/Tests/Public/Users/New-JCUser.tests.ps1 +++ b/PowerShell/JumpCloud Module/Tests/Public/Users/New-JCUser.tests.ps1 @@ -103,6 +103,13 @@ Describe -Tag:('JCUser') 'New-JCUser 1.0' { $NewUser.manager | Should -Be $managerID Remove-JCUser -UserID $NewUser._id -ByID -Force } + It "Creates a new User sets managerEmail" { + $managerEmail = $PesterParams_User1.email + $managerID = $PesterParams_User1.id + $NewUser = New-RandomUser -domain pleasedelete"PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser -manager $managerEmail + $NewUser.manager | Should -Be $managerID + Remove-JCUser -UserID $NewUser._id -ByID -Force + } It "Creates a new User sets alternateEmail" { $alternateEmail = "$((New-RandomString -NumberOfChars 6))ae@DeleteMe.com" $NewUser = New-RandomUser -domain pleasedelete"PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser -alternateEmail $alternateEmail diff --git a/PowerShell/JumpCloud Module/Tests/Public/Users/Set-JCUser.tests.ps1 b/PowerShell/JumpCloud Module/Tests/Public/Users/Set-JCUser.tests.ps1 index 8c1b653a4..1ec815754 100755 --- a/PowerShell/JumpCloud Module/Tests/Public/Users/Set-JCUser.tests.ps1 +++ b/PowerShell/JumpCloud Module/Tests/Public/Users/Set-JCUser.tests.ps1 @@ -78,6 +78,14 @@ Describe -Tag:('JCUser') 'Set-JCUser 1.0' { Remove-JCUser -UserID $NewUser._id -force Remove-JCUser -UserID $ManagerUser._id -force } + It "Updates the managerUsername using email" { + $ManagerUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser + $NewUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser + $NewManager = Set-JCUser -Username $NewUser.Username -manager $ManagerUser.email + $NewManager.manager | Should -Be $ManagerUser.id + Remove-JCUser -UserID $NewUser._id -force + Remove-JCUser -UserID $ManagerUser._id -force + } It "Updates the managerUsername using -ByID and -UserID" { $ManagerUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser $NewUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser @@ -86,6 +94,14 @@ Describe -Tag:('JCUser') 'Set-JCUser 1.0' { Remove-JCUser -UserID $NewUser._id -force Remove-JCUser -UserID $ManagerUser._id -force } + It "Updates the managerEmail using -ByID and -UserID" { + $ManagerUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser + $NewUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser + $NewManager = Set-JCUser -ByID -UserID $NewUser._id -manager $ManagerUser.email + $NewManager.manager | Should -Be $ManagerUser.id + Remove-JCUser -UserID $NewUser._id -force + Remove-JCUser -UserID $ManagerUser._id -force + } It "Updates the managerId using -Username" { $ManagerUser = New-RandomUser "PesterTest$(Get-Date -Format MM-dd-yyyy)" | New-JCUser $ManagerId = $ManagerUser.id diff --git a/PowerShell/ModuleBanner.md b/PowerShell/ModuleBanner.md index b169fabdc..855d9080a 100755 --- a/PowerShell/ModuleBanner.md +++ b/PowerShell/ModuleBanner.md @@ -1,17 +1,17 @@ #### Latest Version ``` -1.21.0 +1.22.0 ``` #### Banner Current ``` -New parameter -recoveryemail for Set, Get, New-JCUser +* Added functionality for Set, Get, New-JCUser to Search by Email to Manager Field ``` #### Banner Old ``` -Get-JcUser, Set-JcUser and New-JcUser will soon be deprecating the -suspended parameter. Please use the -state paramater as a replacement. +* New parameter -recoveryemail for Set, Get, New-JCUser ``` diff --git a/PowerShell/ModuleChangelog.md b/PowerShell/ModuleChangelog.md index a10b1de35..093fbbbd0 100644 --- a/PowerShell/ModuleChangelog.md +++ b/PowerShell/ModuleChangelog.md @@ -1,3 +1,24 @@ +## 1.22.0 + +Release Date: May 16, 2022 + +#### RELEASE NOTES + +This release includes an update to Set, Get, New-JCUser to search manager by a valid JumpCloud user's primary email + +#### IMPROVEMENTS: + +* Set, Get, New-JCUser will validate email address value given to -manager + +#### FEATURES: + +* This release adds email search to manager field in Set, Get, New-JCUser +* This release adds new parameters to Get-JCResults private function + +#### BUG FIXES: + +* Backup-JCOrganization no longer throws a forbidden error message when run with a read-only API Key. + ## 1.21.0 Release Date: May 11, 2022