Skip to content

Commit d237c1a

Browse files
authored
New powershell connector (PSv2) (#14)
* Feat: new powershell connector * Feat: add fieldMapping and updated readme * Fix: Update Logo URL * Fix: Added create action for UsId * Added note for field mapping UsId * Added <CustomerCode> placeholder in UsId * feat: added support voor Site/InSi on enable/disable * fix: updateOnupdate to onlyUpdateOnCorrelate * Fix: auditlogs exceeded data size limit.
1 parent 8ce885a commit d237c1a

8 files changed

Lines changed: 1194 additions & 935 deletions

File tree

README.md

Lines changed: 101 additions & 52 deletions
Large diffs are not rendered by default.

configuration.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,23 +42,23 @@
4242
}
4343
},
4444
{
45-
"key": "createAccount",
45+
"key": "createUser",
4646
"type": "checkbox",
4747
"defaultValue": false,
4848
"templateOptions": {
49-
"label": "Create account when not found",
49+
"label": "Create user when not found",
5050
"required": false,
51-
"description": "When toggled, if the user account is not found, a new AFAS user account will be created in the create action (only in the create action)."
51+
"description": "When toggled, if the user account is not found, a new the AFAS user account will be created in the create action (only in the create action)."
5252
}
5353
},
5454
{
55-
"key": "updateOnCorrelate",
55+
"key": "onlyUpdateOnCorrelate",
5656
"type": "checkbox",
5757
"defaultValue": false,
5858
"templateOptions": {
59-
"label": "Update on correlate",
59+
"label": "Only update on correlate",
6060
"required": false,
61-
"description": "When toggled, if the mapped data differs from data in AFAS, the AFAS user will be updated in the create action (not just correlated)."
61+
"description": "When toggled, the AFAS user will only be updated when the account is correlated"
6262
}
6363
},
6464
{

create.ps1

Lines changed: 137 additions & 427 deletions
Large diffs are not rendered by default.

delete.ps1

Lines changed: 95 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,22 @@
11
#####################################################
22
# HelloID-Conn-Prov-Target-AFAS-Profit-Users-Delete
3-
#
4-
# Version: 2.1.0
3+
# PowerShell V2
54
#####################################################
6-
# Initialize default values
7-
$c = $configuration | ConvertFrom-Json
8-
$p = $person | ConvertFrom-Json
9-
$aRef = $accountReference | ConvertFrom-Json
10-
$success = $false # Set to false at start, at the end, only when no error occurs it is set to true
11-
$auditLogs = [System.Collections.Generic.List[PSCustomObject]]::new()
125

13-
# Set TLS to accept TLS, TLS 1.1 and TLS 1.2
14-
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12
6+
# Set to false at start, at the end, only when no error occurs it is set to true
7+
$outputContext.Success = $false
8+
9+
# AccountReference must have a value for dryRun
10+
$outputContext.AccountReference = $actionContext.References.Account
1511

1612
# Set debug logging
17-
switch ($($c.isDebug)) {
18-
$true { $VerbosePreference = "Continue" }
19-
$false { $VerbosePreference = "SilentlyContinue" }
20-
}
21-
$InformationPreference = "Continue"
22-
$WarningPreference = "Continue"
23-
24-
# Correlation values
25-
$correlationProperty = "Gebruiker" # Has to match the name of the unique identifier
26-
$correlationValue = $aRef.Gebruiker # Has to match the value of the unique identifier
27-
28-
#Change mapping here
29-
$account = [PSCustomObject]@{
30-
# Mutatie code
31-
'MtCd' = 0
32-
# E-mail - Optional to update delete
33-
'EmAd' = "" # or e.g. "$($p.ExternalId)@enyoi.nl" or "$($p.Contact.Personal.Email)"
34-
# UPN - Vulling UPN afstemmen met AFAS beheer - Optional to update on delete
35-
'Upn' = "" # or e.g. "$($p.ExternalId)@enyoi.nl" or "$($p.Contact.Personal.Email)"
36-
37-
# Set properties below to false to remove permissions on delete
38-
# Outsite
39-
"Site" = $false
40-
# InSite
41-
"InSi" = $false
13+
switch ($($actionContext.Configuration.isDebug)) {
14+
$true { $VerbosePreference = 'Continue' }
15+
$false { $VerbosePreference = 'SilentlyContinue' }
4216
}
4317

44-
$updateAccountFields = @("EmAd", "Upn", "Site", "InSi")
45-
46-
# Define account properties to store in account data
47-
$storeAccountFields = @("EmAd", "Upn")
18+
# Enable TLS1.2
19+
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12
4820

4921
#region functions
5022
function Resolve-HTTPError {
@@ -117,10 +89,11 @@ function Get-ErrorMessage {
11789
if ( $($ErrorObject.Exception.GetType().FullName -eq 'Microsoft.PowerShell.Commands.HttpResponseException') -or $($ErrorObject.Exception.GetType().FullName -eq 'System.Net.WebException')) {
11890
$httpErrorObject = Resolve-HTTPError -ErrorObject $ErrorObject
11991

120-
if(-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)){
92+
if (-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)) {
12193
$errorMessage.VerboseErrorMessage = $httpErrorObject.ErrorMessage
12294
$errorMessage.AuditErrorMessage = Resolve-AFASErrorMessage -ErrorObject $httpErrorObject.ErrorMessage
123-
}else{
95+
}
96+
else {
12497
$errorMessage.VerboseErrorMessage = $ErrorObject.Exception.Message
12598
$errorMessage.AuditErrorMessage = $ErrorObject.Exception.Message
12699
}
@@ -140,18 +113,60 @@ function Get-ErrorMessage {
140113
#endregion functions
141114

142115
try {
116+
# Correlation values
117+
$correlationProperty = "Gebruiker" # Has to match the name of the unique identifier
118+
$correlationValue = $actionContext.References.Account.Gebruiker # Has to match the value of the unique identifier
119+
120+
$account = $actionContext.Data
121+
122+
# Remove field because only used for export data or to set correlation
123+
if ($account.PSObject.Properties.Name -Contains 'Gebruiker') {
124+
$account.PSObject.Properties.Remove('Gebruiker')
125+
}
126+
if ($account.PSObject.Properties.Name -Contains 'Medewerker') {
127+
$account.PSObject.Properties.Remove('Medewerker')
128+
}
129+
130+
$updateAccountFields = @()
131+
if ($account.PSObject.Properties.Name -Contains 'EmAd') {
132+
$updateAccountFields += "EmAd"
133+
}
134+
if ($account.PSObject.Properties.Name -Contains 'Upn') {
135+
$updateAccountFields += "Upn"
136+
}
137+
if ($account.PSObject.Properties.Name -Contains 'Site') {
138+
$updateAccountFields += "Site"
139+
}
140+
if ($account.PSObject.Properties.Name -Contains 'InSi') {
141+
$updateAccountFields += "InSi"
142+
}
143+
if ($account.PSObject.Properties.Name -Contains 'Awin') {
144+
$updateAccountFields += "Awin"
145+
}
146+
147+
# Verify if [aRef] has a value
148+
if ([string]::IsNullOrEmpty($($actionContext.References.Account))) {
149+
$outputContext.AuditLogs.Add([PSCustomObject]@{
150+
Action = "DeleteAccount"
151+
Message = "The account reference could not be found"
152+
IsError = $true
153+
})
154+
155+
throw 'The account reference could not be found'
156+
}
157+
143158
# Get current account and verify if there are changes
144159
try {
145160
Write-Verbose "Querying AFAS user where [$($correlationProperty)] = [$($correlationValue)]"
146161

147162
# Create authorization headers
148-
$encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($($c.Token)))
163+
$encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($($actionContext.Configuration.Token)))
149164
$authValue = "AfasToken $encodedToken"
150165
$Headers = @{ Authorization = $authValue }
151166
$Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID
152167

153168
$splatWebRequest = @{
154-
Uri = "$($c.BaseUri)/connectors/$($c.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1"
169+
Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1"
155170
Headers = $headers
156171
Method = 'GET'
157172
ContentType = "application/json;charset=utf-8"
@@ -170,9 +185,9 @@ try {
170185
# UPN
171186
'Upn' = $currentAccount.UPN
172187
# Outsite
173-
"Site" = $currentAccount.OutSite
188+
"Site" = [String]$currentAccount.OutSite
174189
# InSite
175-
"InSi" = $currentAccount.InSite
190+
"InSi" = [String]$currentAccount.InSite
176191
}
177192

178193
# Calculate changes between current data and provided data
@@ -204,22 +219,22 @@ try {
204219
Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)"
205220

206221
if ($errorMessage.AuditErrorMessage -Like "*No AFAS user found*") {
207-
$auditLogs.Add([PSCustomObject]@{
208-
# Action = "" # Optional
222+
$outputContext.AuditLogs.Add([PSCustomObject]@{
223+
Action = "DeleteAccount"
209224
Message = "No AFAS user found where [$($correlationProperty)] = [$($aRef.Gebruiker)]. Possibly already deleted, skipping action."
210225
IsError = $false
211226
})
212227
}
213228
else {
214-
$auditLogs.Add([PSCustomObject]@{
215-
# Action = "" # Optional
229+
$outputContext.AuditLogs.Add([PSCustomObject]@{
230+
Action = "DeleteAccount"
216231
Message = "Error querying AFAS user where [$($correlationProperty)] = [$($aRef.Gebruiker)]. Error Message: $($errorMessage.AuditErrorMessage)"
217232
IsError = $true
218233
})
219234
}
220235

221236
# Skip further actions, as this is a critical error
222-
continue
237+
throw "Error querying AFAS user"
223238
}
224239

225240
# Disable AFAS User
@@ -242,21 +257,21 @@ try {
242257

243258
$body = ($disableAccount | ConvertTo-Json -Depth 10)
244259
$splatWebRequest = @{
245-
Uri = "$($c.BaseUri)/connectors/$($c.UpdateConnector)"
260+
Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.UpdateConnector)"
246261
Headers = $headers
247262
Method = 'PUT'
248263
Body = ([System.Text.Encoding]::UTF8.GetBytes($body))
249264
ContentType = "application/json;charset=utf-8"
250265
UseBasicParsing = $true
251266
}
252267

253-
if (-not($dryRun -eq $true)) {
268+
if (-Not($actionContext.DryRun -eq $true)) {
254269
Write-Verbose "Disabling AFAS user [$($currentAccount.Gebruiker)]"
255270

256271
$disabledAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false
257272

258-
$auditLogs.Add([PSCustomObject]@{
259-
# Action = "" # Optional
273+
$outputContext.AuditLogs.Add([PSCustomObject]@{
274+
Action = "DeleteAccount"
260275
Message = "Successfully disabled AFAS user [$($currentAccount.Gebruiker)]"
261276
IsError = $false
262277
})
@@ -271,11 +286,14 @@ try {
271286

272287
Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)"
273288

274-
$auditLogs.Add([PSCustomObject]@{
275-
# Action = "" # Optional
289+
$outputContext.AuditLogs.Add([PSCustomObject]@{
290+
Action = "DeleteAccount"
276291
Message = "Error disabling AFAS user [$($currentAccount.Gebruiker)]. Error Message: $($errorMessage.AuditErrorMessage)"
277292
IsError = $true
278293
})
294+
295+
# Skip further actions, as this is a critical error
296+
throw "Error disabling AFAS user"
279297
}
280298

281299
switch ($updateAction) {
@@ -322,52 +340,53 @@ try {
322340

323341
$body = ($updateAccount | ConvertTo-Json -Depth 10)
324342
$splatWebRequest = @{
325-
Uri = "$($c.BaseUri)/connectors/$($c.UpdateConnector)"
343+
Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.UpdateConnector)"
326344
Headers = $headers
327345
Method = 'PUT'
328346
Body = ([System.Text.Encoding]::UTF8.GetBytes($body))
329347
ContentType = "application/json;charset=utf-8"
330348
UseBasicParsing = $true
331349
}
332350

333-
if (-not($dryRun -eq $true)) {
351+
if (-Not($actionContext.DryRun -eq $true)) {
334352
Write-Verbose "Updating AFAS user [$($currentAccount.Gebruiker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)"
335353

336354
$updatedAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false
337355

338-
$auditLogs.Add([PSCustomObject]@{
339-
# Action = "" # Optional
356+
$outputContext.AuditLogs.Add([PSCustomObject]@{
357+
Action = "DeleteAccount"
340358
Message = "Successfully updated AFAS user [$($currentAccount.Gebruiker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)"
341359
IsError = $false
342360
})
343361
}
344362
else {
345363
Write-Warning "DryRun: Would update AFAS user [$($currentAccount.Gebruiker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)"
346364
}
347-
348-
break
349365
}
350366
catch {
351367
$ex = $PSItem
352368
$errorMessage = Get-ErrorMessage -ErrorObject $ex
353369

354370
Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)"
355371

356-
$auditLogs.Add([PSCustomObject]@{
357-
# Action = "" # Optional
372+
$outputContext.AuditLogs.Add([PSCustomObject]@{
373+
Action = "DeleteAccount"
358374
Message = "Error updating AFAS user [$($currentAccount.Gebruiker)]. Error Message: $($errorMessage.AuditErrorMessage). Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)"
359375
IsError = $true
360376
})
377+
378+
# Skip further actions, as this is a critical error
379+
throw "Error updating AFAS user"
361380
}
362381

363382
break
364383
}
365384
'NoChanges' {
366385
Write-Verbose "No changes needed for AFAS user [$($currentAccount.Gebruiker)]"
367386

368-
if (-not($dryRun -eq $true)) {
369-
$auditLogs.Add([PSCustomObject]@{
370-
# Action = "" # Optional
387+
if (-Not($actionContext.DryRun -eq $true)) {
388+
$outputContext.AuditLogs.Add([PSCustomObject]@{
389+
Action = "DeleteAccount"
371390
Message = "No changes needed for AFAS user [$($currentAccount.Gebruiker)]"
372391
IsError = $false
373392
})
@@ -379,33 +398,17 @@ try {
379398
break
380399
}
381400
}
382-
383-
# Define ExportData with account fields and correlation property
384-
$exportData = $account.PsObject.Copy() | Select-Object $storeAccountFields
385-
# Add correlation property to exportdata
386-
$exportData | Add-Member -MemberType NoteProperty -Name $correlationProperty -Value $correlationValue -Force
387-
# Add aRef properties to exportdata
388-
foreach ($aRefProperty in $aRef.PSObject.Properties) {
389-
$exportData | Add-Member -MemberType NoteProperty -Name $aRefProperty.Name -Value $aRefProperty.Value -Force
390-
}
401+
}
402+
catch {
403+
$ex = $PSItem
404+
Write-Verbose "ERROR: $ex"
391405
}
392406
finally {
393407
# Check if auditLogs contains errors, if no errors are found, set success to true
394-
if (-NOT($auditLogs.IsError -contains $true)) {
395-
$success = $true
396-
}
397-
398-
# Send results
399-
$result = [PSCustomObject]@{
400-
Success = $success
401-
AccountReference = $aRef
402-
AuditLogs = $auditLogs
403-
PreviousAccount = $previousAccount
404-
Account = $account
405-
406-
# Optionally return data for use in other systems
407-
ExportData = $exportData
408+
if (-NOT($outputContext.AuditLogs.IsError -contains $true)) {
409+
$outputContext.Success = $true
408410
}
409-
410-
Write-Output ($result | ConvertTo-Json -Depth 10)
411+
412+
$outputContext.Data = $account
413+
$outputContext.PreviousData = $previousAccount
411414
}

0 commit comments

Comments
 (0)