<# 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 } }