Files
2026-07-09 14:51:22 -04:00

88 lines
3.6 KiB
PowerShell

<#
Minimal client for the Polaris Leap (PAPI) Notices endpoint.
PowerShell port of ../polaris_client.py -- see that file's docstrings and
../README.md ("Notes on the API") for the non-obvious quirks this encodes.
#>
class PolarisClient {
[string]$AuthUrl
[string]$BaseUrl
[string]$SiteDomain
[string]$AccessToken
[string]$AccessSecret
PolarisClient(
[string]$Server,
[string]$SiteDomain,
[string]$OrganizationId,
[string]$WorkstationId,
[string]$Language,
[string]$ProductId
) {
# authentication/staffuser is the one route that omits siteDomain/orgId/workstationId --
# those describe a *logged-on* session, and you're not logged on yet at this point.
$this.AuthUrl = "https://$Server/Polaris.ApplicationServices/api/v1/$Language/$ProductId/authentication/staffuser"
$this.BaseUrl = "https://$Server/Polaris.ApplicationServices/api/v1/$Language/$ProductId/$SiteDomain/$OrganizationId/$WorkstationId"
$this.SiteDomain = $SiteDomain
}
# Exchange a staff username/password for an AccessToken/AccessSecret.
# Username must include the domain, e.g. MYLIB\Aladdin.
[void] Authenticate([string]$Username, [string]$Password) {
$pair = "${Username}:${Password}"
$basicAuth = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($pair))
$headers = @{
Authorization = "Basic $basicAuth"
Accept = "application/json"
}
try {
$response = Invoke-RestMethod -Uri $this.AuthUrl -Method Post -Headers $headers
} catch {
$statusCode = $null
if ($_.Exception.Response) { $statusCode = [int]$_.Exception.Response.StatusCode }
if ($statusCode -eq 401) {
throw "Authentication failed: check username/password."
}
throw "Authentication failed ($statusCode): $($_.ErrorDetails.Message)"
}
$this.AccessToken = $response.AccessToken
$this.AccessSecret = $response.AccessSecret
}
hidden [string] AuthHeader() {
if (-not $this.AccessToken -or -not $this.AccessSecret) {
throw "Not authenticated yet -- call Authenticate() first."
}
return "PAS $($this.SiteDomain):$($this.AccessToken):$($this.AccessSecret)"
}
# POST notices for the given notice type to the given org IDs.
# DeliveryOption: only 1 (Mail) is currently supported by the API.
[bool] PostNotices([int]$NoticeType, [int[]]$OrganizationIds, [int]$DeliveryOption) {
$orgIdsCsv = ($OrganizationIds -join ",")
$uri = "$($this.BaseUrl)/notices/post?noticeType=$NoticeType&deliveryOption=$DeliveryOption"
$headers = @{
Authorization = $this.AuthHeader()
Accept = "application/json"
}
# Polaris expects the org-id CSV as a JSON-encoded string literal, matching
# json.dumps(org_ids_csv) on the Python side -- not a raw/unquoted string.
$bodyJson = $orgIdsCsv | ConvertTo-Json
try {
$result = Invoke-RestMethod -Uri $uri -Method Post -Headers $headers -ContentType "application/json" -Body $bodyJson
} catch {
$statusCode = $null
if ($_.Exception.Response) { $statusCode = [int]$_.Exception.Response.StatusCode }
throw "Notice post failed ($statusCode): $($_.ErrorDetails.Message)"
}
if ($result -ne $true) {
throw "Polaris reported failure (returned $result) for noticeType=$NoticeType, organizationIds=$orgIdsCsv"
}
return $result
}
}