Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion src/IdLE.Core/Public/Invoke-IdleProviderMethod.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -66,13 +66,21 @@ function Invoke-IdleProviderMethod {
[string] $MethodName,

[Parameter(Mandatory)]
[AllowNull()]
Comment thread
blindzero marked this conversation as resolved.
[AllowEmptyCollection()]
[object[]] $MethodArguments
)

# Auth session acquisition (optional, data-only)
$authSession = $null


# [AllowNull()] on $MethodArguments is required so PowerShell's parameter binder accepts
# [object[]] arrays that contain $null elements (e.g., a $null attribute value to clear).
# However, the array reference itself must never be null - that would indicate a caller bug.
if ($null -eq $MethodArguments) {
throw "MethodArguments must not be null. Pass an empty array if no arguments are needed."
}

# Validate AuthSessionOptions early (regardless of broker availability)
if ($With.ContainsKey('AuthSessionOptions')) {
$sessionOptions = $With.AuthSessionOptions
Expand Down
32 changes: 32 additions & 0 deletions tests/Steps/Invoke-IdleStepEnsureAttributes.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,38 @@ Describe 'Invoke-IdleStepEnsureAttributes (built-in step)' {
$attributeNames | Should -Contain 'Title'
$attributeNames | Should -Contain 'Office'
}

It 'passes $null attribute values without error (regression: MethodArguments binding)' {
# When attributes contain $null values (e.g., to unset/clear an attribute),
# Invoke-IdleProviderMethod must not fail with "Cannot bind argument to parameter
# 'MethodArguments' because it is null." - caused by PS binding an [object[]]
# containing $null elements to a [Mandatory] parameter without [AllowNull()].
$step = [pscustomobject]@{
Name = 'Unset phone attributes'
Type = 'IdLE.Step.EnsureAttributes'
With = @{
Provider = 'Identity'
IdentityKey = 'user@contoso.com'
Attributes = @{
mobile = $null
telephoneNumber = $null
}
}
}

$handler = 'IdLE.Steps.Common\Invoke-IdleStepEnsureAttributes'
{ & $handler -Context $script:Context -Step $step } | Should -Not -Throw

# Both attributes should have been called with $null value
$callsByName = @{}
$script:FakeProviderLegacy.CallLog | ForEach-Object {
$callsByName[$_.Name] = $_
}
$callsByName.Keys | Should -Contain 'mobile'
$callsByName.Keys | Should -Contain 'telephoneNumber'
$callsByName['mobile'].Value | Should -BeNullOrEmpty
$callsByName['telephoneNumber'].Value | Should -BeNullOrEmpty
}
}

Context 'StepResult shape' {
Expand Down