Providers/Authentik/Public/New-AuthentikInvitation.ps1
|
function New-AuthentikInvitation { <# .EXTERNALHELP TestEnvironment-Help.xml .SYNOPSIS Creates the seeded enrolment invitations from Data\AuthentikInvitations.csv #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] [OutputType([PSCustomObject])] param( [Parameter()] [string[]]$InvitationName, [Parameter()] [switch]$PassThru ) $connection = Get-AuthentikConnection $marker = Get-AuthentikSeedMarker -Connection $connection $csvPath = Join-Path -Path (Get-AuthentikDataPath) -ChildPath 'AuthentikInvitations.csv' $rows = @(Import-Csv -Path $csvPath -Encoding UTF8) if ($InvitationName) { $rows = @($rows | Where-Object { $InvitationName -contains $_.Name }) $unknown = @($InvitationName | Where-Object { $rows.Name -notcontains $_ }) if ($unknown) { throw "No definition in $csvPath for: $($unknown -join ', ')" } } $result = [PSCustomObject]@{ TotalInvitations = $rows.Count CreatedInvitations = 0 UpdatedInvitations = 0 Invitations = @() Errors = @() } $existingByName = @{} foreach ($existing in (Get-AuthentikSeededObject -Type Invitations -Connection $connection)) { $existingByName[[string]$existing.name] = $existing } # An invitation tied to a flow can be redeemed only through that flow. The seeded flows # are resolved by the slug the flows file gives them, so the CSV never sees a UUID. $flowPkByKey = @{} if (@($rows | Where-Object { $_.Flow }).Count -gt 0) { $flowRows = @(Import-Csv -Path (Join-Path -Path (Get-AuthentikDataPath) -ChildPath 'AuthentikFlows.csv') -Encoding UTF8) $seededFlows = @(Get-AuthentikSeededObject -Type Flows -Connection $connection) foreach ($flowRow in $flowRows) { $slug = '{0}-{1}' -f $marker.SlugPrefix, $flowRow.Slug $match = @($seededFlows | Where-Object { $_.slug -eq $slug }) if ($match.Count -gt 0) { $flowPkByKey[$flowRow.Name] = [string]$match[0].pk } } } $invitations = [System.Collections.Generic.List[object]]::new() foreach ($row in $rows) { $name = '{0}-{1}' -f $marker.SlugPrefix, $row.Name if (-not $PSCmdlet.ShouldProcess($name, 'Create Authentik invitation')) { continue } try { $fixedData = ConvertFrom-AuthentikSetting -Text $row.FixedData $fixedData[$marker.Attribute] = $marker.Tag $expires = [DateTimeOffset]::UtcNow.AddDays([int]$row.ExpiresInDays) $body = @{ name = $name expires = $expires.ToString('o') single_use = ($row.SingleUse -eq 'TRUE') fixed_data = $fixedData } $flowSlug = $null if ($row.Flow) { if ($flowPkByKey.ContainsKey($row.Flow)) { $body.flow = $flowPkByKey[$row.Flow] $flowSlug = $row.Flow } else { $message = "Invitation '$name' is tied to flow '$($row.Flow)', which does not exist. Created for any flow." $result.Errors += $message Write-Warning $message } } $invitation = $null if ($existingByName.ContainsKey($name)) { $invitation = Invoke-AuthentikRequest -Method PATCH -Path "/stages/invitation/invitations/$($existingByName[$name].pk)/" -Body $body -Connection $connection $result.UpdatedInvitations++ Write-Verbose "Updated invitation $name" } else { $invitation = Invoke-AuthentikRequest -Method POST -Path '/stages/invitation/invitations/' -Body $body -Connection $connection $result.CreatedInvitations++ Write-Verbose "Created invitation $name" } $invitations.Add([PSCustomObject]@{ Id = [string]$invitation.pk Key = $row.Name Name = $name Expires = $expires.UtcDateTime SingleUse = ($row.SingleUse -eq 'TRUE') Flow = $flowSlug }) } catch { $message = "Failed to create invitation '$name': $($_.Exception.Message)" $result.Errors += $message Write-Error $message } } $result.Invitations = $invitations.ToArray() Write-Verbose ("Invitations: $($result.CreatedInvitations) created, $($result.UpdatedInvitations) updated, " + "$($result.Errors.Count) problems") if ($PassThru) { return $result } } |