Skip to content

Commit 65fb576

Browse files
committed
adduserbulk go brrr
1 parent 9da444e commit 65fb576

File tree

1 file changed

+123
-34
lines changed

1 file changed

+123
-34
lines changed
Lines changed: 123 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
using namespace System.Net
22

3-
Function Invoke-AddUserBulk {
3+
function Invoke-AddUserBulk {
44
<#
55
.FUNCTIONALITY
66
Entrypoint
@@ -13,49 +13,138 @@ Function Invoke-AddUserBulk {
1313
$APIName = 'AddUserBulk'
1414
Write-LogMessage -headers $Request.Headers -API $APINAME -message 'Accessed this API' -Sev 'Debug'
1515
$TenantFilter = $Request.body.TenantFilter
16-
$Body = foreach ($userobj in $request.body.BulkUser) {
17-
if ($userobj.usageLocation.value) {
18-
$userobj.usageLocation = $userobj.usageLocation.value
16+
17+
$BulkUsers = $Request.Body.BulkUser
18+
19+
if (!$BulkUsers) {
20+
$Body = @{
21+
Results = @{
22+
resultText = 'No users specified to import'
23+
state = 'error'
24+
}
1925
}
20-
try {
21-
$password = if ($userobj.password) { $userobj.password } else { New-passwordString }
22-
$UserprincipalName = "$($userobj.mailNickName)@$($userobj.domain)"
23-
$BodyToship = $userobj
24-
#Remove domain from body to ship
25-
$BodyToship = $BodyToship | Select-Object * -ExcludeProperty password, domain
26-
$BodyToship | Add-Member -NotePropertyName accountEnabled -NotePropertyValue $true -Force
27-
$BodyToship | Add-Member -NotePropertyName userPrincipalName -NotePropertyValue $UserprincipalName -Force
28-
$BodyToship | Add-Member -NotePropertyName passwordProfile -NotePropertyValue @{'password' = $password; 'forceChangePasswordNextSignIn' = $true } -Force
29-
Write-Host "body is now: $($BodyToship | ConvertTo-Json -Depth 10 -Compress)"
30-
if ($userobj.businessPhones) { $bodytoShip.businessPhones = @($userobj.businessPhones) }
31-
$bodyToShip = ConvertTo-Json -Depth 10 -InputObject $BodyToship -Compress
32-
Write-Host "Our body to ship is $bodyToShip"
33-
$GraphRequest = New-GraphPostRequest -uri 'https://graph.microsoft.com/beta/users' -tenantid $TenantFilter -type POST -body $BodyToship
34-
Write-Host "Graph request is $GraphRequest"
35-
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($TenantFilter) -message "Created user $($userobj.displayname) with id $($GraphRequest.id) " -Sev 'Info'
36-
37-
#PWPush
38-
$PasswordLink = New-PwPushLink -Payload $password
39-
if ($PasswordLink) {
40-
$password = $PasswordLink
26+
} else {
27+
$BulkRequests = [System.Collections.Generic.List[object]]::new()
28+
$Results = [System.Collections.Generic.List[object]]::new()
29+
$Messages = [System.Collections.Generic.List[object]]::new()
30+
foreach ($User in $BulkUsers) {
31+
# User input validation
32+
$missingFields = [System.Collections.Generic.List[string]]::new()
33+
if (!$User.mailNickName) { $missingFields.Add('mailNickName') }
34+
if (!$User.domain) { $missingFields.Add('domain') }
35+
if (!$User.displayName -and !$User.givenName -and !$User.surname) { $missingFields.Add('displayName') }
36+
37+
$Name = if ([string]::IsNullOrEmpty($User.displayName)) {
38+
'{0} {1}' -f $User.givenName, $User.surname
39+
} else {
40+
$User.displayName
41+
}
42+
43+
# Check for missing required fields
44+
if ($missingFields.Count -gt 0) {
45+
$Results.Add(@{
46+
resultText = "Required fields missing for $($User ?? 'No name specified'): $($missingFields -join ', ')"
47+
state = 'error'
48+
})
49+
} else {
50+
# Create user body with required properties
51+
$Password = if ($User.password) { $User.password } else { New-passwordString }
52+
$UserBody = @{
53+
accountEnabled = $true
54+
displayName = $Name
55+
mailNickName = $User.mailNickName
56+
userPrincipalName = '{0}@{1}' -f $User.mailNickName, $User.domain
57+
passwordProfile = @{
58+
password = $Password
59+
forceChangePasswordNextSignIn = $true
60+
}
61+
}
62+
63+
# Add optional properties if not null or empty
64+
if (![string]::IsNullOrEmpty($User.usageLocation)) {
65+
$UserBody.usageLocation = $User.usageLocation.value ?? $User.usageLocation
66+
}
67+
68+
# Convert businessPhones to array if not null or empty
69+
if (![string]::IsNullOrEmpty($User.businessPhones)) {
70+
$UserBody.businessPhones = @($User.businessPhones)
71+
}
72+
73+
# loop through rest of post body and add to user body if not null or empty or not already set in the user body
74+
foreach ($key in $User.PSObject.Properties.Name) {
75+
if ($key -notin @('displayName', 'mailNickName', 'domain', 'password', 'usageLocation', 'businessPhones')) {
76+
if (![string]::IsNullOrEmpty($User.$key) -and $UserBody.$key -eq $null) {
77+
$UserBody.$key = $User.$key
78+
}
79+
}
80+
}
81+
82+
# Build bulk request
83+
$BulkRequests.Add(@{
84+
'id' = $UserBody.userPrincipalName
85+
'url' = 'users'
86+
'method' = 'POST'
87+
'body' = $UserBody
88+
'headers' = @{
89+
'Content-Type' = 'application/json'
90+
}
91+
})
92+
93+
# Create password link
94+
$PasswordLink = New-PwPushLink -Payload $password
95+
if ($PasswordLink) {
96+
$password = $PasswordLink
97+
}
98+
99+
# Set success messages
100+
$Messages.Add(@{
101+
id = $UserBody.userPrincipalName
102+
resultText = "Created user for $($Name) with username $($UserBody.userPrincipalName)"
103+
copyField = $Password
104+
})
41105
}
42-
$results = "Created user $($UserprincipalName). Password is $password"
106+
}
43107

44-
} catch {
45-
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($TenantFilter) -message "Failed to create user. Error:$($_.Exception.Message)" -Sev 'Error'
46-
$results = "Failed to create user $($UserprincipalName). $($_.Exception.Message)"
108+
if ($BulkRequests.Count -gt 0) {
109+
Write-Warning "We have $($BulkRequests.Count) users to import"
110+
Write-Information ($BulkRequests | ConvertTo-Json -Depth 5)
111+
$BulkResults = New-GraphBulkRequest -tenantid $TenantFilter -Requests $BulkRequests
112+
Write-Warning "We have $($BulkResults.Count) results"
113+
Write-Information ($BulkResults | ConvertTo-Json -Depth 10
114+
)
115+
foreach ($BulkResult in $BulkResults) {
116+
if ($BulkResult.status -ne 201) {
117+
Write-LogMessage -headers $Request.Headers -API $APINAME -tenant $($TenantFilter) -message "Failed to create user $($BulkResult.id). Error:$($BulkResult.body.error.message)" -Sev 'Error'
118+
$Results.Add(@{
119+
resultText = "Failed to create user $($BulkResult.id). Error: $($BulkResult.body.error.message)"
120+
state = 'error'
121+
})
122+
} else {
123+
$Message = $Messages.Where({ $_.id -eq $BulkResult.id })
124+
$Results.Add(@{
125+
resultText = $Message.resultText
126+
state = 'success'
127+
copyField = $Message.copyField
128+
username = $BulkResult.body.userPrincipalName
129+
id = $BulkResult.id
130+
})
131+
}
132+
}
133+
} else {
134+
$Results.Add(@{
135+
resultText = 'No users to import'
136+
state = 'error'
137+
})
47138
}
48-
[PSCustomObject]@{
49-
'Results' = $results
50-
'Username' = $UserprincipalName
51-
'Password' = $password
139+
$Body = @{
140+
Results = @($Results)
52141
}
53142
}
54143

55144
# Associate values to output bindings by calling 'Push-OutputBinding'.
56145
Push-OutputBinding -Name Response -Value ([HttpResponseContext]@{
57146
StatusCode = [HttpStatusCode]::OK
58-
Body = @($Body)
147+
Body = $Body
59148
})
60149

61150
}

0 commit comments

Comments
 (0)