Skip to content

Commit 8491835

Browse files
author
rvdwegen
committed
Bulk the patch user endpoint
1 parent 1056fa3 commit 8491835

File tree

1 file changed

+73
-7
lines changed
  • Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users

1 file changed

+73
-7
lines changed

Modules/CIPPCore/Public/Entrypoints/HTTP Functions/Identity/Administration/Users/Invoke-PatchUser.ps1

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ function Invoke-PatchUser {
1010

1111
$APIName = $Request.Params.CIPPEndpoint
1212
$Headers = $Request.Headers
13-
$tenantFilter = $Request.Body.tenantFilter
1413
Write-LogMessage -headers $Headers -API $APIName -message 'Accessed this API' -Sev 'Debug'
1514

1615
$HttpResponse = [HttpResponseContext]@{
@@ -19,18 +18,85 @@ function Invoke-PatchUser {
1918
}
2019

2120
try {
22-
$UserObj = $Request.Body | Select-Object -Property * -ExcludeProperty tenantFilter
23-
if ([string]::IsNullOrWhiteSpace($UserObj.id)) {
21+
# Handle array of user objects or single user object
22+
$Users = if ($Request.Body -is [array]) {
23+
$Request.Body
24+
} else {
25+
@($Request.Body)
26+
}
27+
28+
# Validate that all users have required properties
29+
$InvalidUsers = $Users | Where-Object {
30+
[string]::IsNullOrWhiteSpace($_.id) -or [string]::IsNullOrWhiteSpace($_.tenantFilter)
31+
}
32+
if ($InvalidUsers.Count -gt 0) {
2433
$HttpResponse.StatusCode = [HttpStatusCode]::BadRequest
25-
$HttpResponse.Body = @{'Results' = @('Failed to patch user. No user ID provided') }
34+
$HttpResponse.Body = @{'Results' = @('Failed to patch user(s). Some users are missing id or tenantFilter') }
2635
} else {
27-
$null = New-GraphPostRequest -uri "https://graph.microsoft.com/beta/users/$($UserObj.id)" -tenantid $tenantFilter -type PATCH -body $($UserObj | ConvertTo-Json)
28-
$HttpResponse.Body = @{'Results' = @("Properties on user $($UserObj.id) patched successfully") }
36+
# Group users by tenant filter
37+
$UsersByTenant = $Users | Group-Object -Property tenantFilter
38+
39+
$TotalSuccessCount = 0
40+
$AllErrorMessages = @()
41+
42+
# Process each tenant separately
43+
foreach ($TenantGroup in $UsersByTenant) {
44+
$tenantFilter = $TenantGroup.Name
45+
$TenantUsers = $TenantGroup.Group
46+
47+
# Build bulk requests for this tenant
48+
$int = 0
49+
$BulkRequests = foreach ($User in $TenantUsers) {
50+
# Remove the id and tenantFilter properties from the body since they're not user properties
51+
$PatchBody = $User | Select-Object -Property * -ExcludeProperty id, tenantFilter
52+
53+
@{
54+
id = $int++
55+
method = 'PATCH'
56+
url = "users/$($User.id)"
57+
body = $PatchBody
58+
'headers' = @{
59+
'Content-Type' = 'application/json'
60+
}
61+
}
62+
}
63+
64+
# Execute bulk request for this tenant
65+
$BulkResults = New-GraphBulkRequest -tenantid $tenantFilter -Requests @($BulkRequests)
66+
67+
# Process results for this tenant
68+
for ($i = 0; $i -lt $BulkResults.Count; $i++) {
69+
$result = $BulkResults[$i]
70+
$user = $TenantUsers[$i]
71+
72+
if ($result.status -eq 200 -or $result.status -eq 204) {
73+
$TotalSuccessCount++
74+
Write-LogMessage -headers $Headers -API $APIName -tenant $tenantFilter -message "Successfully patched user $($user.id)" -Sev 'Info'
75+
} else {
76+
$errorMsg = if ($result.body.error.message) {
77+
$result.body.error.message
78+
} else {
79+
"Unknown error (Status: $($result.status))"
80+
}
81+
$AllErrorMessages += "Failed to patch user $($user.id) in tenant $($tenantFilter): $errorMsg"
82+
Write-LogMessage -headers $Headers -API $APIName -tenant $tenantFilter -message "Failed to patch user $($user.id). Error: $errorMsg" -Sev 'Error'
83+
}
84+
}
85+
}
86+
87+
# Build final response
88+
if ($AllErrorMessages.Count -eq 0) {
89+
$TenantCount = ($Users | Select-Object -Property tenantFilter -Unique).Count
90+
$HttpResponse.Body = @{'Results' = @("Successfully patched $TotalSuccessCount user$(if($TotalSuccessCount -ne 1){'s'}) across $TenantCount tenant$(if($TenantCount -ne 1){'s'})") }
91+
} else {
92+
$HttpResponse.StatusCode = [HttpStatusCode]::BadRequest
93+
$HttpResponse.Body = @{'Results' = $AllErrorMessages + @("Successfully patched $TotalSuccessCount of $($Users.Count) users") }
94+
}
2995
}
3096

3197
} catch {
3298
$HttpResponse.StatusCode = [HttpStatusCode]::InternalServerError
33-
$HttpResponse.Body = @{'Results' = @("Failed to patch user. Error: $($_.Exception.Message)") }
99+
$HttpResponse.Body = @{'Results' = @("Failed to patch user(s). Error: $($_.Exception.Message)") }
34100
}
35101

36102
Push-OutputBinding -Name Response -Value $HttpResponse

0 commit comments

Comments
 (0)