diff --git a/Mapping/EmAd.js b/Mapping/EmAd.js new file mode 100644 index 0000000..9a77efa --- /dev/null +++ b/Mapping/EmAd.js @@ -0,0 +1,11 @@ +function getEmAd() { + let mail = ''; + + if (typeof Person.Accounts.MicrosoftActiveDirectory.mail !== 'undefined' && Person.Accounts.MicrosoftActiveDirectory.mail) { + mail = Person.Accounts.MicrosoftActiveDirectory.mail; + } + + return mail; +} + +getEmAd() \ No newline at end of file diff --git a/README.md b/README.md index a5d0c9b..ee065fe 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,10 @@ Repository for HelloID Provisioning Target Connector to AFAS Employees Issues Badge GitHub contributors +| :warning: Warning | +| :---------------- | +| This script is for the new powershell connector. Make sure to use the mapping and correlation keys like mentionded in this readme. For more information, please read our [documentation](https://docs.helloid.com/en/provisioning/target-systems/powershell-v2-target-systems.html) | + | :information_source: Information | |:---------------------------| @@ -27,6 +31,8 @@ Repository for HelloID Provisioning Target Connector to AFAS Employees - [Remarks](#remarks) - [Scope](#scope) - [UpdateConnector](#updateconnector) + - [Mapping](#mapping) + - [Correlation](#correlation) - [Getting help](#getting-help) - [HelloID docs](#helloid-docs) @@ -39,9 +45,9 @@ The HelloID connector consists of the template scripts shown in the following ta | Action | Action(s) Performed | Comment | | ------------------------------- | --------------------- | --------- | -| create.ps1 | Update AFAS employee | | -| update.ps1 | Update AFAS employee | | -| delete.ps1 | Update AFAS employee | Clear the unique fields, since the values have to be unique over all AFAS environments | +| create.ps1 | Update AFAS employee | Correlates AFAS employee | +| update.ps1 | Update AFAS employee | Update on correlate and update on update | +| delete.ps1 | Update AFAS employee | Clear the unique fields, since the values have to be unique over all AFAS environments | ## Getting Started @@ -67,7 +73,7 @@ The following settings are required to connect to the API. | Token in XML format | The AppConnector token to connect to AFAS | Yes | | Get Connector | The GetConnector in AFAS to query the user with | Yes | | Update Connector | The UpdateConnector in AFAS to update the user with | Yes | -| Update on correlate | When toggled, if the mapped data differs from data in AFAS, the AFAS employee will be updated in the create action (not just correlated). | No | +| Update on update | When toggled, if the mapped data differs from data in AFAS, the AFAS user will be updated when a update is triggerd. | No | | Toggle debug logging | When toggled, extra logging is shown. Note that this is only meant for debugging, please switch this off when in production. | No | ### Prerequisites @@ -80,7 +86,7 @@ The following settings are required to connect to the API. ### GetConnector When the connector is defined as target system, only the following GetConnector is used by HelloID: -* Tools4ever - HelloID - T4E_HelloID_Users_v2 +* Tools4ever - HelloID - T4E_HelloID_Users_v2 #### Remarks - In view of GDPR, the persons private data, such as private email address and birthdate are not in the data collection by default. When needed for the implementation (e.g. set emailaddress with private email address on delete), these properties will have to be added. @@ -97,7 +103,29 @@ The data collection can be changed by the customer itself to meet their requirem ### UpdateConnector In addition to use to the above get-connector, the connector also uses the following build-in Profit update-connectors: -* knEmployee +* knEmployee + +### Mapping +The mandatory and recommended field mapping is listed below. + +| Name | Create | Enable | Update | Disable | Delete | Store in account data | Default mapping | Mandatory | Comment | +| -------------- | ------ | ------ | ------ | ------- | ------ | --------------------- | ------------------------------------------ | --------- | ---------------------------------------------- | +| Medewerker | X | | X | | | Yes | Field: ExternalId | Yes | Used for Correlation and to store account data | +| Persoonsnummer | X | | X | | | Yes | None | Yes | Used to store account data | +| EmAd | | | X | | X | Yes | Update: Complex EmAd.js Delete Fixed empty | | E-Mail werk | + +The fields listed below are examples of available fields for mapping but are typically not used. + +| Name | Create | Enable | Update | Disable | Delete | Store in account data | Default mapping | Mandatory | Comment | +| ----------- | ------ | ------ | ------ | ------- | ------ | --------------------- | -------------------------------------- | --------- | ---------------------------------------------------------------------- | +| EmailPortal | | | X | | X | Yes | for example UPN | | E-mail toegang - Check with AFAS Administrator if this needs to be set | +| TeNr | | | X | | X | Yes | | | Telefoonnr. werk | +| MbNr | | | X | | X | Yes | | | Mobiel werk | + + +### Correlation +It is mandatory to enable the correlation in the correlation tab. The default value for "person correlation field" is " ExternalId". The default value for "Account Correlation field" is "Medewerker". + ## Getting help > _For more information on how to configure a HelloID PowerShell connector, please refer to our [documentation](https://docs.helloid.com/hc/en-us/articles/360012558020-Configure-a-custom-PowerShell-target-system) pages_ diff --git a/configuration.json b/configuration.json index 0f0c829..bb40485 100644 --- a/configuration.json +++ b/configuration.json @@ -42,13 +42,13 @@ } }, { - "key": "updateOnCorrelate", + "key": "updateOnUpdate", "type": "checkbox", "defaultValue": false, "templateOptions": { - "label": "Update on correlate", + "label": "Update on update", "required": false, - "description": "When toggled, if the mapped data differs from data in AFAS, the AFAS employee will be updated in the create action (not just correlated)." + "description": "When toggled, if the mapped data differs from data in AFAS, the AFAS user will be updated when a update is triggerd" } }, { diff --git a/create.ps1 b/create.ps1 index 523d301..b614baa 100644 --- a/create.ps1 +++ b/create.ps1 @@ -1,50 +1,45 @@ ##################################################### # HelloID-Conn-Prov-Target-AFAS-Profit-Employees-Create # -# Version: 2.1.0 +# Version: 3.0.0 | new-powershell-connector ##################################################### -# Initialize default values -$c = $configuration | ConvertFrom-Json -$p = $person | ConvertFrom-Json -$aRef = "Unknown" # Set to "Unknown" at start, because it is required for a preview, but isn't set in preview. The actual run will overwrite this with the actual aRef. -$success = $false # Set to false at start, at the end, only when no error occurs it is set to true -$auditLogs = [System.Collections.Generic.List[PSCustomObject]]::new() -# Set TLS to accept TLS, TLS 1.1 and TLS 1.2 -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 +# Set to true at start, because only when an error occurs it is set to false +$outputContext.Success = $true + +# AccountReference must have a value for dryRun +$outputContext.AccountReference = "Unknown" # Set debug logging -switch ($($c.isDebug)) { - $true { $VerbosePreference = "Continue" } - $false { $VerbosePreference = "SilentlyContinue" } +switch ($($actionContext.Configuration.isDebug)) { + $true { $VerbosePreference = 'Continue' } + $false { $VerbosePreference = 'SilentlyContinue' } } -$InformationPreference = "Continue" -$WarningPreference = "Continue" -# Correlation values -$correlationProperty = "Medewerker" # Has to match the name of the unique identifier -$correlationValue = $p.ExternalId # Has to match the value of the unique identifier +# Enable TLS1.2 +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 -#Change mapping here -$account = [PSCustomObject]@{ - # E-Mail werk - 'EmAd' = $p.Accounts.MicrosoftActiveDirectory.mail +if ($actionContext.CorrelationConfiguration.Enabled) { + $correlationProperty = $actionContext.CorrelationConfiguration.accountField + $correlationValue = $actionContext.CorrelationConfiguration.accountFieldValue - # E-mail toegang - Check with AFAS Administrator if this needs to be set - 'EmailPortal' = $p.Accounts.MicrosoftActiveDirectory.userPrincipalName + if ([string]::IsNullOrEmpty($correlationProperty)) { + Write-Warning "Correlation is enabled but not configured correctly." + Throw "Correlation is enabled but not configured correctly." + } - # # Telefoonnr. werk - # 'TeNr' = '0229123456' - - # # Mobiel werk - # 'MbNr' = '0612345678' + if ([string]::IsNullOrEmpty($correlationValue)) { + Write-Warning "The correlation value for [$correlationProperty] is empty. This is likely a scripting issue." + Throw "The correlation value for [$correlationProperty] is empty. This is likely a scripting issue." + } +} +else { + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Message = "Configuration of correlation is madatory." + IsError = $true + }) + Throw "Configuration of correlation is madatory." } - -# Define account properties to update -$updateAccountFields = @("EmAd") - -# Define account properties to store in account data -$storeAccountFields = @("EmAd", "EmailPortal") #region functions function Resolve-HTTPError { @@ -117,10 +112,11 @@ function Get-ErrorMessage { if ( $($ErrorObject.Exception.GetType().FullName -eq 'Microsoft.PowerShell.Commands.HttpResponseException') -or $($ErrorObject.Exception.GetType().FullName -eq 'System.Net.WebException')) { $httpErrorObject = Resolve-HTTPError -ErrorObject $ErrorObject - if(-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)){ + if (-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)) { $errorMessage.VerboseErrorMessage = $httpErrorObject.ErrorMessage $errorMessage.AuditErrorMessage = Resolve-AFASErrorMessage -ErrorObject $httpErrorObject.ErrorMessage - }else{ + } + else { $errorMessage.VerboseErrorMessage = $ErrorObject.Exception.Message $errorMessage.AuditErrorMessage = $ErrorObject.Exception.Message } @@ -139,267 +135,64 @@ function Get-ErrorMessage { } #endregion functions +# Get current account and verify if there are changes try { - # Get current account and verify if the action should be either [updated and correlated] or just [correlated] - try { - Write-Verbose "Querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" - - # Create authorization headers - $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($c.Token)) - $authValue = "AfasToken $encodedToken" - $Headers = @{ Authorization = $authValue } - $Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID - - $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" - Headers = $headers - Method = 'GET' - ContentType = "application/json;charset=utf-8" - UseBasicParsing = $true - } - $currentAccount = (Invoke-RestMethod @splatWebRequest -Verbose:$false).rows - - if ($null -eq $currentAccount.Medewerker) { - throw "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" - } - - # Retrieve current account data for properties to be updated - $previousAccount = [PSCustomObject]@{ - # E-Mail werk - 'EmAd' = $currentAccount.Email_werk - # E-mail toegang - 'EmailPortal' = $currentAccount.Email_portal - # Telefoonnr. werk - 'TeNr' = $currentAccount.Telefoonnr_werk - # Mobiel werk - 'MbNr' = $currentAccount.Mobielnr_werk - } - - if ($c.updateOnCorrelate -eq $true) { - $action = 'Update' - - # Calculate changes between current data and provided data - $splatCompareProperties = @{ - ReferenceObject = @($previousAccount.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update - DifferenceObject = @($account.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update - } - $changedProperties = $null - $changedProperties = (Compare-Object @splatCompareProperties -PassThru) - $oldProperties = $changedProperties.Where( { $_.SideIndicator -eq '<=' }) - $newProperties = $changedProperties.Where( { $_.SideIndicator -eq '=>' }) - - if (($newProperties | Measure-Object).Count -ge 1) { - Write-Verbose "Changed properties: $($changedProperties | ConvertTo-Json)" - - $updateAction = 'Update' - } - else { - Write-Verbose "No changed properties" - - $updateAction = 'NoChanges' - } - } - else { - $action = 'Correlate' - } + Write-Verbose "Querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" + + # Create authorization headers + $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($actionContext.Configuration.Token)) + $authValue = "AfasToken $encodedToken" + $Headers = @{ Authorization = $authValue } + $Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID + + $splatWebRequest = @{ + Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" + Headers = $headers + Method = 'GET' + ContentType = "application/json;charset=utf-8" + UseBasicParsing = $true } - catch { - $ex = $PSItem - $errorMessage = Get-ErrorMessage -ErrorObject $ex + $currentAccount = (Invoke-RestMethod @splatWebRequest -Verbose:$false).rows - Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" + if ($null -eq $currentAccount.Medewerker) { + throw "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" + } - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Error querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Error Message: $($errorMessage.AuditErrorMessage)" - IsError = $true + if (-Not($actionContext.DryRun -eq $true)) { + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "CorrelateAccount" + Message = "Correlated account [$($currentAccount.Medewerker)] on field [$($correlationProperty)] with value [$($correlationValue)]" + IsError = $false }) - # Skip further actions, as this is a critical error - continue + $aRef = [PSCustomObject]@{ + Medewerker = $currentAccount.Medewerker + Persoonsnummer = $currentAccount.Persoonsnummer + } + $outputContext.AccountCorrelated = $true + $outputContext.AccountReference = $aRef + } + else { + Write-Warning "DryRun: Would correlate AFAS employee [$($currentAccount.Medewerker)]." } - # Either [update and correlate] or just [correlate] - switch ($action) { - 'Update' { - switch ($updateAction) { - 'Update' { - # Update AFAS Employee - try { - # Create custom object with old and new values - $changedPropertiesObject = [PSCustomObject]@{ - OldValues = @{} - NewValues = @{} - } - - # Add the old properties to the custom object with old and new values - foreach ($oldProperty in ($oldProperties | Where-Object { $_.Name -in $newProperties.Name })) { - $changedPropertiesObject.OldValues.$($oldProperty.Name) = $oldProperty.Value - } - - # Add the new properties to the custom object with old and new values - foreach ($newProperty in $newProperties) { - $changedPropertiesObject.NewValues.$($newProperty.Name) = $newProperty.Value - } - Write-Verbose "Changed properties: $($changedPropertiesObject | ConvertTo-Json)" - - # Create custom account object for update and set with default properties and values - $updateAccount = [PSCustomObject]@{ - 'AfasEmployee' = @{ - 'Element' = @{ - '@EmId' = $currentAccount.Medewerker - 'Objects' = @(@{ - 'KnPerson' = @{ - 'Element' = @{ - 'Fields' = @{ - # Zoek op BcCo (Persoons-ID) - 'MatchPer' = 0 - # Nummer - 'BcCo' = $currentAccount.Persoonsnummer - } - } - } - }) - } - } - } - - # Add the updated properties to the custom account object for update - Only add changed properties. AFAS will throw an error when trying to update this with the same value - foreach ($newProperty in $newProperties ) { - $updateAccount.AfasEmployee.Element.Objects[0].KnPerson.Element.Fields.$($newProperty.Name) = $newProperty.Value - } - - $body = ($updateAccount | ConvertTo-Json -Depth 10) - $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.UpdateConnector)" - Headers = $headers - Method = 'PUT' - Body = ([System.Text.Encoding]::UTF8.GetBytes($body)) - ContentType = "application/json;charset=utf-8" - UseBasicParsing = $true - } - - if (-not($dryRun -eq $true)) { - Write-Verbose "Updating AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - - $updatedAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false - - # Set aRef object for use in futher actions - $aRef = [PSCustomObject]@{ - Medewerker = $currentAccount.Medewerker - Persoonsnummer = $currentAccount.Persoonsnummer - } - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Successfully updated AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - IsError = $false - }) - } - else { - Write-Warning "DryRun: Would update AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - } - } - catch { - $ex = $PSItem - $errorMessage = Get-ErrorMessage -ErrorObject $ex - - Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Error updating AFAS employee [$($currentAccount.Medewerker)]. Error Message: $($errorMessage.AuditErrorMessage). Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - IsError = $true - }) - } - - break - } - 'NoChanges' { - Write-Verbose "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - - if (-not($dryRun -eq $true)) { - # Set aRef object for use in futher actions - $aRef = [PSCustomObject]@{ - Medewerker = $currentAccount.Medewerker - Persoonsnummer = $currentAccount.Persoonsnummer - } - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - IsError = $false - }) - } - else { - Write-Warning "DryRun: No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - } - break - } - } - - # Define ExportData with account fields and correlation property - $exportData = $account.PsObject.Copy() | Select-Object $storeAccountFields - # Add correlation property to exportdata - $exportData | Add-Member -MemberType NoteProperty -Name $correlationProperty -Value $correlationValue -Force - # Add aRef properties to exportdata - foreach ($aRefProperty in $aRef.PSObject.Properties) { - $exportData | Add-Member -MemberType NoteProperty -Name $aRefProperty.Name -Value $aRefProperty.Value -Force - } - - break - } - 'Correlate' { - Write-Verbose "Correlating to AFAS employee [$($currentAccount.Medewerker)]" - - if (-not($dryRun -eq $true)) { - # Set aRef object for use in futher actions - $aRef = [PSCustomObject]@{ - Medewerker = $currentAccount.Medewerker - Persoonsnummer = $currentAccount.Persoonsnummer - } +} +catch { + $ex = $PSItem + $errorMessage = Get-ErrorMessage -ErrorObject $ex - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Successfully correlated to AFAS employee [$($currentAccount.Medewerker)]" - IsError = $false - }) - } - else { - Write-Warning "DryRun: Would correlate to AFAS employee [$($currentAccount.Medewerker)]" - } + Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" - # Define ExportData with account fields and correlation property - $exportData = $account.PsObject.Copy() | Select-Object $storeAccountFields - # Add correlation property to exportdata - $exportData | Add-Member -MemberType NoteProperty -Name $correlationProperty -Value $correlationValue -Force - # Add aRef properties to exportdata - foreach ($aRefProperty in $aRef.PSObject.Properties) { - $exportData | Add-Member -MemberType NoteProperty -Name $aRefProperty.Name -Value $aRefProperty.Value -Force - } - - break - } - } + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "CorrelateAccount" + Message = "Error querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Error Message: $($errorMessage.AuditErrorMessage)" + IsError = $true + }) } finally { - # Check if auditLogs contains errors, if no errors are found, set success to true - if (-NOT($auditLogs.IsError -contains $true)) { - $success = $true - } - - # Send results - $result = [PSCustomObject]@{ - Success = $success - AccountReference = $aRef - AuditLogs = $auditLogs - PreviousAccount = $previousAccount - Account = $account - - # Optionally return data for use in other systems - ExportData = $exportData + # Check if auditLogs contains errors, if errors are found, set succes to false + if ($outputContext.AuditLogs.IsError -contains $true) { + $outputContext.Success = $false } - - Write-Output ($result | ConvertTo-Json -Depth 10) -} +} \ No newline at end of file diff --git a/delete.ps1 b/delete.ps1 index 9384b23..d938643 100644 --- a/delete.ps1 +++ b/delete.ps1 @@ -1,50 +1,49 @@ ##################################################### # HelloID-Conn-Prov-Target-AFAS-Profit-Employees-Delete # -# Version: 2.1.0 +# Version: 3.0.0 | new-powershell-connector ##################################################### -# Initialize default values -$c = $configuration | ConvertFrom-Json -$p = $person | ConvertFrom-Json -$aRef = $accountReference | ConvertFrom-Json -$success = $false # Set to false at start, at the end, only when no error occurs it is set to true -$auditLogs = [System.Collections.Generic.List[PSCustomObject]]::new() -# Set TLS to accept TLS, TLS 1.1 and TLS 1.2 -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 +# Set to true at start, because only when an error occurs it is set to false +$outputContext.Success = $true # Set debug logging -switch ($($c.isDebug)) { - $true { $VerbosePreference = "Continue" } - $false { $VerbosePreference = "SilentlyContinue" } +switch ($($actionContext.Configuration.isDebug)) { + $true { $VerbosePreference = 'Continue' } + $false { $VerbosePreference = 'SilentlyContinue' } } -$InformationPreference = "Continue" -$WarningPreference = "Continue" - -# Correlation values -$correlationProperty = "Medewerker" # Has to match the name of the unique identifier -$correlationValue = $p.ExternalId # Has to match the value of the unique identifier - -#Change mapping here -$account = [PSCustomObject]@{ - # E-Mail werk - 'EmAd' = "" # or e.g. "$($aRef.Medewerker)@domain.com" - Unique value because at the revoke action we want to clear the unique fields - - # E-mail toegang - Check with AFAS Administrator if this needs to be set - 'EmailPortal' = "" # or e.g. "$($aRef.Medewerker)@domain.com" - Unique value because at the revoke action we want to clear the unique fields - - # # Telefoonnr. werk - # 'TeNr' = '0229123456' - - # # Mobiel werk - # 'MbNr' = '0612345678' + +# Enable TLS1.2 +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 + +$account = $actionContext.Data + +$correlationProperty = $actionContext.CorrelationConfiguration.accountField +$correlationValue = $actionContext.References.Account.Medewerker # Has to match the AFAS value of the specified filter field ($filterfieldid) + +if ([string]::IsNullOrEmpty($correlationProperty)) { + Write-Warning "Correlation is enabled but not configured correctly." + Throw "Correlation is enabled but not configured correctly." } -# Define account properties to update -$updateAccountFields = @("EmAd") +if ([string]::IsNullOrEmpty($correlationValue)) { + Write-Warning "The correlation value for [$correlationProperty] is empty. Account Refference is empty." + Throw "The correlation value for [$correlationProperty] is empty. Account Refference is empty." +} -# Define account properties to store in account data -$storeAccountFields = @("EmAd", "EmailPortal") +$updateAccountFields = @() +if ($account.PSObject.Properties.Name -Contains 'EmAd') { + $updateAccountFields += "EmAd" +} +if ($account.PSObject.Properties.Name -Contains 'EmailPortal') { + $updateAccountFields += "EmailPortal" +} +if ($account.PSObject.Properties.Name -Contains 'TeNr') { + $updateAccountFields += "TeNr" +} +if ($account.PSObject.Properties.Name -Contains 'MbNr') { + $updateAccountFields += "MbNr" +} #region functions function Resolve-HTTPError { @@ -140,19 +139,19 @@ function Get-ErrorMessage { } #endregion functions +# Get current account and verify if there are changes try { - # Get current account and verify if there are changes try { Write-Verbose "Querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" # Create authorization headers - $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($c.Token)) + $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($actionContext.Configuration.Token)) $authValue = "AfasToken $encodedToken" $Headers = @{ Authorization = $authValue } $Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" + Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" Headers = $headers Method = 'GET' ContentType = "application/json;charset=utf-8" @@ -193,7 +192,7 @@ try { } else { Write-Verbose "No changed properties" - + $updateAction = 'NoChanges' } } @@ -204,15 +203,15 @@ try { Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" if ($errorMessage.AuditErrorMessage -Like "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]") { - $auditLogs.Add([PSCustomObject]@{ - Action = "CreateAccount" + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "DeleteAccount" Message = "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Possibly deleted." - IsError = $true + IsError = $false }) } else { - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "DeleteAccount" Message = "Error querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Error Message: $($errorMessage.AuditErrorMessage)" IsError = $true }) @@ -221,7 +220,7 @@ try { # Skip further actions, as this is a critical error continue } - + switch ($updateAction) { 'Update' { # Update AFAS Employee @@ -271,7 +270,7 @@ try { $body = ($updateAccount | ConvertTo-Json -Depth 10) $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.UpdateConnector)" + Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.UpdateConnector)" Headers = $headers Method = 'PUT' Body = ([System.Text.Encoding]::UTF8.GetBytes($body)) @@ -279,9 +278,9 @@ try { UseBasicParsing = $true } - if (-not($dryRun -eq $true)) { + if (-Not($actionContext.DryRun -eq $true)) { Write-Verbose "Updating AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - + $updatedAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false # Set aRef object for use in futher actions @@ -289,9 +288,9 @@ try { Medewerker = $currentAccount.Medewerker Persoonsnummer = $currentAccount.Persoonsnummer } - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional + + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "DeleteAccount" Message = "Successfully updated AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" IsError = $false }) @@ -303,11 +302,11 @@ try { catch { $ex = $PSItem $errorMessage = Get-ErrorMessage -ErrorObject $ex - - Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional + Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" + + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "DeleteAccount" Message = "Error updating AFAS employee [$($currentAccount.Medewerker)]. Error Message: $($errorMessage.AuditErrorMessage). Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" IsError = $true }) @@ -318,15 +317,15 @@ try { 'NoChanges' { Write-Verbose "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - if (-not($dryRun -eq $true)) { + if (-Not($actionContext.DryRun -eq $true)) { # Set aRef object for use in futher actions $aRef = [PSCustomObject]@{ Medewerker = $currentAccount.Medewerker Persoonsnummer = $currentAccount.Persoonsnummer } - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "DeleteAccount" Message = "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" IsError = $false }) @@ -338,33 +337,21 @@ try { break } } - +} +finally { + # Check if auditLogs contains errors, if errors are found, set succes to false + if ($outputContext.AuditLogs.IsError -contains $true) { + $outputContext.Success = $false + } # Define ExportData with account fields and correlation property - $exportData = $account.PsObject.Copy() | Select-Object $storeAccountFields + $exportData = $account.PsObject.Copy() # Add correlation property to exportdata $exportData | Add-Member -MemberType NoteProperty -Name $correlationProperty -Value $correlationValue -Force # Add aRef properties to exportdata foreach ($aRefProperty in $aRef.PSObject.Properties) { $exportData | Add-Member -MemberType NoteProperty -Name $aRefProperty.Name -Value $aRefProperty.Value -Force } -} -finally { - # Check if auditLogs contains errors, if no errors are found, set success to true - if (-NOT($auditLogs.IsError -contains $true)) { - $success = $true - } - - # Send results - $result = [PSCustomObject]@{ - Success = $success - AccountReference = $aRef - AuditLogs = $auditLogs - PreviousAccount = $previousAccount - Account = $account - - # Optionally return data for use in other systems - ExportData = $exportData - } - - Write-Output ($result | ConvertTo-Json -Depth 10) + $outputContext.AccountReference = $aRef + $outputContext.Data = $exportData + $outputContext.PreviousData = $previousAccount } \ No newline at end of file diff --git a/update.ps1 b/update.ps1 index b7d0eba..a4e7ce4 100644 --- a/update.ps1 +++ b/update.ps1 @@ -1,50 +1,52 @@ ##################################################### # HelloID-Conn-Prov-Target-AFAS-Profit-Employees-Update # -# Version: 2.1.0 +# Version: 3.0.0 | new-powershell-connector ##################################################### -# Initialize default values -$c = $configuration | ConvertFrom-Json -$p = $person | ConvertFrom-Json -$aRef = $accountReference | ConvertFrom-Json -$success = $false # Set to false at start, at the end, only when no error occurs it is set to true -$auditLogs = [System.Collections.Generic.List[PSCustomObject]]::new() -# Set TLS to accept TLS, TLS 1.1 and TLS 1.2 -[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls -bor [Net.SecurityProtocolType]::Tls11 -bor [Net.SecurityProtocolType]::Tls12 +# Set to true at start, because only when an error occurs it is set to false +$outputContext.Success = $true + +# AccountReference must have a value for dryRun +$aRef = $actionContext.References.Account # Set debug logging -switch ($($c.isDebug)) { - $true { $VerbosePreference = "Continue" } - $false { $VerbosePreference = "SilentlyContinue" } +switch ($($actionContext.Configuration.isDebug)) { + $true { $VerbosePreference = 'Continue' } + $false { $VerbosePreference = 'SilentlyContinue' } } -$InformationPreference = "Continue" -$WarningPreference = "Continue" -# Correlation values -$correlationProperty = "Medewerker" # Has to match the name of the unique identifier -$correlationValue = $p.ExternalId # Has to match the value of the unique identifier +# Enable TLS1.2 +[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [System.Net.SecurityProtocolType]::Tls12 -#Change mapping here -$account = [PSCustomObject]@{ - # E-Mail werk - 'EmAd' = $p.Accounts.MicrosoftActiveDirectory.mail +$account = $actionContext.Data - # E-mail toegang - Check with AFAS Administrator if this needs to be set - 'EmailPortal' = $p.Accounts.MicrosoftActiveDirectory.userPrincipalName +$correlationProperty = $actionContext.CorrelationConfiguration.accountField +$correlationValue = $actionContext.References.Account.Medewerker # Has to match the AFAS value of the specified filter field ($filterfieldid) - # # Telefoonnr. werk - # 'TeNr' = '0229123456' - - # # Mobiel werk - # 'MbNr' = '0612345678' +if ([string]::IsNullOrEmpty($correlationProperty)) { + Write-Warning "Correlation is enabled but not configured correctly." + Throw "Correlation is enabled but not configured correctly." } -# Define account properties to update -$updateAccountFields = @("EmAd") +if ([string]::IsNullOrEmpty($correlationValue)) { + Write-Warning "The correlation value for [$correlationProperty] is empty. Account Refference is empty." + Throw "The correlation value for [$correlationProperty] is empty. Account Refference is empty." +} -# Define account properties to store in account data -$storeAccountFields = @("EmAd", "EmailPortal") +$updateAccountFields = @() +if ($account.PSObject.Properties.Name -Contains 'EmAd') { + $updateAccountFields += "EmAd" +} +if ($account.PSObject.Properties.Name -Contains 'EmailPortal') { + $updateAccountFields += "EmailPortal" +} +if ($account.PSObject.Properties.Name -Contains 'TeNr') { + $updateAccountFields += "TeNr" +} +if ($account.PSObject.Properties.Name -Contains 'MbNr') { + $updateAccountFields += "MbNr" +} #region functions function Resolve-HTTPError { @@ -117,10 +119,11 @@ function Get-ErrorMessage { if ( $($ErrorObject.Exception.GetType().FullName -eq 'Microsoft.PowerShell.Commands.HttpResponseException') -or $($ErrorObject.Exception.GetType().FullName -eq 'System.Net.WebException')) { $httpErrorObject = Resolve-HTTPError -ErrorObject $ErrorObject - if(-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)){ + if (-not[String]::IsNullOrEmpty($httpErrorObject.ErrorMessage)) { $errorMessage.VerboseErrorMessage = $httpErrorObject.ErrorMessage $errorMessage.AuditErrorMessage = Resolve-AFASErrorMessage -ErrorObject $httpErrorObject.ErrorMessage - }else{ + } + else { $errorMessage.VerboseErrorMessage = $ErrorObject.Exception.Message $errorMessage.AuditErrorMessage = $ErrorObject.Exception.Message } @@ -137,224 +140,218 @@ function Get-ErrorMessage { Write-Output $errorMessage } } -#endregion functions - try { - # Get current account and verify if there are changes - try { - Write-Verbose "Querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" - - # Create authorization headers - $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($c.Token)) - $authValue = "AfasToken $encodedToken" - $Headers = @{ Authorization = $authValue } - $Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID - - $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" - Headers = $headers - Method = 'GET' - ContentType = "application/json;charset=utf-8" - UseBasicParsing = $true - } - $currentAccount = (Invoke-RestMethod @splatWebRequest -Verbose:$false).rows + #endregion functions + if (($actionContext.Configuration.updateOnUpdate -eq $true) -or ($actionContext.AccountCorrelated -eq $true)) { + # Get current account and verify if there are changes + try { + Write-Verbose "Querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" + + # Create authorization headers + $encodedToken = [System.Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes($actionContext.Configuration.Token)) + $authValue = "AfasToken $encodedToken" + $Headers = @{ Authorization = $authValue } + $Headers.Add("IntegrationId", "45963_140664") # Fixed value - Tools4ever Partner Integration ID + + $splatWebRequest = @{ + Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.GetConnector)?filterfieldids=$($correlationProperty)&filtervalues=$($correlationValue)&operatortypes=1" + Headers = $headers + Method = 'GET' + ContentType = "application/json;charset=utf-8" + UseBasicParsing = $true + } + $currentAccount = (Invoke-RestMethod @splatWebRequest -Verbose:$false).rows - if ($null -eq $currentAccount.Medewerker) { - throw "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" - } + if ($null -eq $currentAccount.Medewerker) { + throw "No AFAS employee found AFAS employee where [$($correlationProperty)] = [$($correlationValue)]" + } - # Retrieve current account data for properties to be updated - $previousAccount = [PSCustomObject]@{ - # E-Mail werk - 'EmAd' = $currentAccount.Email_werk - # E-mail toegang - 'EmailPortal' = $currentAccount.Email_portal - # Telefoonnr. werk - 'TeNr' = $currentAccount.Telefoonnr_werk - # Mobiel werk - 'MbNr' = $currentAccount.Mobielnr_werk - } - # Calculate changes between current data and provided data - $splatCompareProperties = @{ - ReferenceObject = @($previousAccount.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update - DifferenceObject = @($account.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update - } - $changedProperties = $null - $changedProperties = (Compare-Object @splatCompareProperties -PassThru) - $oldProperties = $changedProperties.Where( { $_.SideIndicator -eq '<=' }) - $newProperties = $changedProperties.Where( { $_.SideIndicator -eq '=>' }) + # Retrieve current account data for properties to be updated + $previousAccount = [PSCustomObject]@{ + # E-Mail werk + 'EmAd' = $currentAccount.Email_werk + # E-mail toegang + 'EmailPortal' = $currentAccount.Email_portal + # Telefoonnr. werk + 'TeNr' = $currentAccount.Telefoonnr_werk + # Mobiel werk + 'MbNr' = $currentAccount.Mobielnr_werk + } - if (($newProperties | Measure-Object).Count -ge 1) { - Write-Verbose "Changed properties: $($changedProperties | ConvertTo-Json)" - $updateAction = 'Update' - } - else { - Write-Verbose "No changed properties" - - $updateAction = 'NoChanges' + # Calculate changes between current data and provided data + $splatCompareProperties = @{ + ReferenceObject = @($previousAccount.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update + DifferenceObject = @($account.PSObject.Properties | Where-Object { $_.Name -in $updateAccountFields }) # Only select the properties to update + } + $changedProperties = $null + $changedProperties = (Compare-Object @splatCompareProperties -PassThru) + $oldProperties = $changedProperties.Where( { $_.SideIndicator -eq '<=' }) + $newProperties = $changedProperties.Where( { $_.SideIndicator -eq '=>' }) + + if (($newProperties | Measure-Object).Count -ge 1) { + Write-Verbose "Changed properties: $($changedProperties | ConvertTo-Json)" + + $updateAction = 'Update' + } + else { + Write-Verbose "No changed properties" + + $updateAction = 'NoChanges' + } } - } - catch { - $ex = $PSItem - $errorMessage = Get-ErrorMessage -ErrorObject $ex + catch { + $ex = $PSItem + $errorMessage = Get-ErrorMessage -ErrorObject $ex - Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" + Write-Verbose "Error at Line [$($ex.InvocationInfo.ScriptLineNumber)]: $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Error querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Error Message: $($errorMessage.AuditErrorMessage)" - IsError = $true - }) + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "UpdateAccount" + Message = "Error querying AFAS employee where [$($correlationProperty)] = [$($correlationValue)]. Error Message: $($errorMessage.AuditErrorMessage)" + IsError = $true + }) - # Skip further actions, as this is a critical error - continue - } - - switch ($updateAction) { - 'Update' { - # Update AFAS Employee - try { - # Create custom object with old and new values - $changedPropertiesObject = [PSCustomObject]@{ - OldValues = @{} - NewValues = @{} - } + # Skip further actions, as this is a critical error + continue + } - # Add the old properties to the custom object with old and new values - foreach ($oldProperty in ($oldProperties | Where-Object { $_.Name -in $newProperties.Name })) { - $changedPropertiesObject.OldValues.$($oldProperty.Name) = $oldProperty.Value - } + switch ($updateAction) { + 'Update' { + # Update AFAS Employee + try { + # Create custom object with old and new values + $changedPropertiesObject = [PSCustomObject]@{ + OldValues = @{} + NewValues = @{} + } - # Add the new properties to the custom object with old and new values - foreach ($newProperty in $newProperties) { - $changedPropertiesObject.NewValues.$($newProperty.Name) = $newProperty.Value - } - Write-Verbose "Changed properties: $($changedPropertiesObject | ConvertTo-Json)" - - # Create custom account object for update and set with default properties and values - $updateAccount = [PSCustomObject]@{ - 'AfasEmployee' = @{ - 'Element' = @{ - '@EmId' = $currentAccount.Medewerker - 'Objects' = @(@{ - 'KnPerson' = @{ - 'Element' = @{ - 'Fields' = @{ - # Zoek op BcCo (Persoons-ID) - 'MatchPer' = 0 - # Nummer - 'BcCo' = $currentAccount.Persoonsnummer + # Add the old properties to the custom object with old and new values + foreach ($oldProperty in ($oldProperties | Where-Object { $_.Name -in $newProperties.Name })) { + $changedPropertiesObject.OldValues.$($oldProperty.Name) = $oldProperty.Value + } + + # Add the new properties to the custom object with old and new values + foreach ($newProperty in $newProperties) { + $changedPropertiesObject.NewValues.$($newProperty.Name) = $newProperty.Value + } + Write-Verbose "Changed properties: $($changedPropertiesObject | ConvertTo-Json)" + + # Create custom account object for update and set with default properties and values + $updateAccount = [PSCustomObject]@{ + 'AfasEmployee' = @{ + 'Element' = @{ + '@EmId' = $currentAccount.Medewerker + 'Objects' = @(@{ + 'KnPerson' = @{ + 'Element' = @{ + 'Fields' = @{ + # Zoek op BcCo (Persoons-ID) + 'MatchPer' = 0 + # Nummer + 'BcCo' = $currentAccount.Persoonsnummer + } } } - } - }) + }) + } } } - } - # Add the updated properties to the custom account object for update - Only add changed properties. AFAS will throw an error when trying to update this with the same value - foreach ($newProperty in $newProperties ) { - $updateAccount.AfasEmployee.Element.Objects[0].KnPerson.Element.Fields.$($newProperty.Name) = $newProperty.Value - } + # Add the updated properties to the custom account object for update - Only add changed properties. AFAS will throw an error when trying to update this with the same value + foreach ($newProperty in $newProperties ) { + $updateAccount.AfasEmployee.Element.Objects[0].KnPerson.Element.Fields.$($newProperty.Name) = $newProperty.Value + } + + $body = ($updateAccount | ConvertTo-Json -Depth 10) + $splatWebRequest = @{ + Uri = "$($actionContext.Configuration.BaseUri)/connectors/$($actionContext.Configuration.UpdateConnector)" + Headers = $headers + Method = 'PUT' + Body = ([System.Text.Encoding]::UTF8.GetBytes($body)) + ContentType = "application/json;charset=utf-8" + UseBasicParsing = $true + } + + if (-Not($actionContext.DryRun -eq $true)) { + Write-Verbose "Updating AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" + + $updatedAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false - $body = ($updateAccount | ConvertTo-Json -Depth 10) - $splatWebRequest = @{ - Uri = "$($c.BaseUri)/connectors/$($c.UpdateConnector)" - Headers = $headers - Method = 'PUT' - Body = ([System.Text.Encoding]::UTF8.GetBytes($body)) - ContentType = "application/json;charset=utf-8" - UseBasicParsing = $true + # Set aRef object for use in futher actions + $aRef = [PSCustomObject]@{ + Medewerker = $currentAccount.Medewerker + Persoonsnummer = $currentAccount.Persoonsnummer + } + + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "UpdateAccount" + Message = "Successfully updated AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" + IsError = $false + }) + } + else { + Write-Warning "DryRun: Would update AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" + } + } + catch { + $ex = $PSItem + $errorMessage = Get-ErrorMessage -ErrorObject $ex + + Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" + + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "UpdateAccount" + Message = "Error updating AFAS employee [$($currentAccount.Medewerker)]. Error Message: $($errorMessage.AuditErrorMessage). Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" + IsError = $true + }) } - if (-not($dryRun -eq $true)) { - Write-Verbose "Updating AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - - $updatedAccount = Invoke-RestMethod @splatWebRequest -Verbose:$false + break + } + 'NoChanges' { + Write-Verbose "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" + if (-Not($actionContext.DryRun -eq $true)) { # Set aRef object for use in futher actions $aRef = [PSCustomObject]@{ Medewerker = $currentAccount.Medewerker Persoonsnummer = $currentAccount.Persoonsnummer } - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Successfully updated AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" + + $outputContext.AuditLogs.Add([PSCustomObject]@{ + Action = "UpdateAccount" + Message = "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" IsError = $false }) } else { - Write-Warning "DryRun: Would update AFAS employee [$($currentAccount.Medewerker)]. Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - } - } - catch { - $ex = $PSItem - $errorMessage = Get-ErrorMessage -ErrorObject $ex - - Write-Verbose "Error at Line '$($ex.InvocationInfo.ScriptLineNumber)': $($ex.InvocationInfo.Line). Error: $($errorMessage.VerboseErrorMessage)" - - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "Error updating AFAS employee [$($currentAccount.Medewerker)]. Error Message: $($errorMessage.AuditErrorMessage). Old values: $($changedPropertiesObject.oldValues | ConvertTo-Json -Depth 10). New values: $($changedPropertiesObject.newValues | ConvertTo-Json -Depth 10)" - IsError = $true - }) - } - - break - } - 'NoChanges' { - Write-Verbose "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - - if (-not($dryRun -eq $true)) { - # Set aRef object for use in futher actions - $aRef = [PSCustomObject]@{ - Medewerker = $currentAccount.Medewerker - Persoonsnummer = $currentAccount.Persoonsnummer + Write-Warning "DryRun: No changes needed for AFAS employee [$($currentAccount.Medewerker)]" } - $auditLogs.Add([PSCustomObject]@{ - # Action = "" # Optional - Message = "No changes needed for AFAS employee [$($currentAccount.Medewerker)]" - IsError = $false - }) - } - else { - Write-Warning "DryRun: No changes needed for AFAS employee [$($currentAccount.Medewerker)]" + break } - - break } } - + else { + $previousAccount = $account + } +} +finally { + # Check if auditLogs contains errors, if errors are found, set succes to false + if ($outputContext.AuditLogs.IsError -contains $true) { + $outputContext.Success = $false + } # Define ExportData with account fields and correlation property - $exportData = $account.PsObject.Copy() | Select-Object $storeAccountFields + $exportData = $account.PsObject.Copy() # Add correlation property to exportdata $exportData | Add-Member -MemberType NoteProperty -Name $correlationProperty -Value $correlationValue -Force # Add aRef properties to exportdata foreach ($aRefProperty in $aRef.PSObject.Properties) { $exportData | Add-Member -MemberType NoteProperty -Name $aRefProperty.Name -Value $aRefProperty.Value -Force } -} -finally { - # Check if auditLogs contains errors, if no errors are found, set success to true - if (-NOT($auditLogs.IsError -contains $true)) { - $success = $true - } - - # Send results - $result = [PSCustomObject]@{ - Success = $success - AccountReference = $aRef - AuditLogs = $auditLogs - PreviousAccount = $previousAccount - Account = $account - - # Optionally return data for use in other systems - ExportData = $exportData - } - - Write-Output ($result | ConvertTo-Json -Depth 10) + $outputContext.AccountReference = $aRef + $outputContext.Data = $exportData + $outputContext.PreviousData = $previousAccount } \ No newline at end of file