Converted to PowerShell
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
<#
|
||||
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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
# PowerShell version
|
||||
|
||||
Same functionality as the Python scripts in the repo root, ported for running on Windows
|
||||
Servers via Task Scheduler without needing a Python install.
|
||||
|
||||
## Setup
|
||||
|
||||
No dependencies to install — `Invoke-RestMethod` is built into Windows PowerShell 5.1+.
|
||||
|
||||
Uses the same `.env` file as the Python version (see `../.env.example`); by default it looks
|
||||
for `..\.env` relative to this script. Pass `-EnvFile` to point elsewhere, e.g. if you'd rather
|
||||
keep credentials outside the repo checkout entirely.
|
||||
|
||||
## Usage
|
||||
|
||||
```powershell
|
||||
.\post_notices.ps1 -NoticeType 2 -OrgIds 3,4,5,6,7,8
|
||||
```
|
||||
|
||||
- `-NoticeType`: the Notification Type ID to post.
|
||||
- `-OrgIds`: comma-separated Organization IDs to post notices for.
|
||||
- `-DeliveryOption`: optional, defaults to `1` (Mail) — currently the only value Polaris accepts.
|
||||
|
||||
Same caveat as the Python version: every run sends real notices to real patrons, and there's no
|
||||
dry-run mode.
|
||||
|
||||
## Task Scheduler
|
||||
|
||||
Action: `powershell.exe`
|
||||
Arguments: `-NoProfile -ExecutionPolicy Bypass -File "C:\path\to\PowerShell\post_notices.ps1" -NoticeType 2 -OrgIds 3,4,5,6,7,8`
|
||||
|
||||
If your Windows PowerShell execution policy blocks unsigned scripts by default, `-ExecutionPolicy
|
||||
Bypass` on the scheduled task action avoids having to change the machine-wide policy.
|
||||
@@ -0,0 +1,94 @@
|
||||
<#
|
||||
.SYNOPSIS
|
||||
Posts notices to Polaris via the Leap (PAPI) API. PowerShell port of ../post_notices.py.
|
||||
|
||||
.EXAMPLE
|
||||
.\post_notices.ps1 -NoticeType 2 -OrgIds 3,4,5,6,7,8
|
||||
#>
|
||||
|
||||
[CmdletBinding()]
|
||||
param(
|
||||
[Parameter(Mandatory = $true)]
|
||||
[int]$NoticeType,
|
||||
|
||||
[Parameter(Mandatory = $true)]
|
||||
[string]$OrgIds,
|
||||
|
||||
[int]$DeliveryOption = 1,
|
||||
|
||||
# Defaults to a .env file next to the repo root (one level up from this script),
|
||||
# matching where the Python version expects it.
|
||||
[string]$EnvFile = (Join-Path $PSScriptRoot "..\.env")
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
. (Join-Path $PSScriptRoot "PolarisClient.ps1")
|
||||
|
||||
function Import-DotEnv {
|
||||
param([string]$Path)
|
||||
if (-not (Test-Path -LiteralPath $Path)) { return }
|
||||
|
||||
foreach ($line in Get-Content -LiteralPath $Path) {
|
||||
$trimmed = $line.Trim()
|
||||
if (-not $trimmed -or $trimmed.StartsWith('#')) { continue }
|
||||
|
||||
$idx = $trimmed.IndexOf('=')
|
||||
if ($idx -lt 1) { continue }
|
||||
|
||||
$key = $trimmed.Substring(0, $idx).Trim()
|
||||
$value = $trimmed.Substring($idx + 1).Trim()
|
||||
if ($value.Length -ge 2 -and (
|
||||
($value[0] -eq '"' -and $value[-1] -eq '"') -or
|
||||
($value[0] -eq "'" -and $value[-1] -eq "'")
|
||||
)) {
|
||||
$value = $value.Substring(1, $value.Length - 2)
|
||||
}
|
||||
|
||||
# Don't clobber a value already set in the environment (e.g. via Task Scheduler).
|
||||
if (-not (Get-Item -Path "Env:$key" -ErrorAction SilentlyContinue).Value) {
|
||||
Set-Item -Path "Env:$key" -Value $value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Import-DotEnv -Path $EnvFile
|
||||
|
||||
$requiredEnv = @(
|
||||
"POLARIS_SERVER",
|
||||
"POLARIS_SITE_DOMAIN",
|
||||
"POLARIS_ORGANIZATION_ID",
|
||||
"POLARIS_WORKSTATION_ID",
|
||||
"POLARIS_USERNAME",
|
||||
"POLARIS_PASSWORD"
|
||||
)
|
||||
$missing = $requiredEnv | Where-Object { [string]::IsNullOrWhiteSpace((Get-Item -Path "Env:$_" -ErrorAction SilentlyContinue).Value) }
|
||||
if ($missing) {
|
||||
Write-Error "Missing required .env values: $($missing -join ', ')"
|
||||
Write-Error "Copy .env.example to .env and fill it in (or set these as environment variables)."
|
||||
exit 1
|
||||
}
|
||||
|
||||
$orgIdList = $OrgIds -split "," | Where-Object { $_.Trim() } | ForEach-Object { [int]$_.Trim() }
|
||||
|
||||
$language = if ($env:POLARIS_LANGUAGE) { $env:POLARIS_LANGUAGE } else { "eng" }
|
||||
$productId = if ($env:POLARIS_PRODUCT_ID) { $env:POLARIS_PRODUCT_ID } else { "7" }
|
||||
|
||||
$client = [PolarisClient]::new(
|
||||
$env:POLARIS_SERVER,
|
||||
$env:POLARIS_SITE_DOMAIN,
|
||||
$env:POLARIS_ORGANIZATION_ID,
|
||||
$env:POLARIS_WORKSTATION_ID,
|
||||
$language,
|
||||
$productId
|
||||
)
|
||||
|
||||
try {
|
||||
$client.Authenticate($env:POLARIS_USERNAME, $env:POLARIS_PASSWORD)
|
||||
$client.PostNotices($NoticeType, $orgIdList, $DeliveryOption) | Out-Null
|
||||
} catch {
|
||||
Write-Error "Error: $($_.Exception.Message)"
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output "Notices posted successfully: noticeType=$NoticeType, orgIds=$($orgIdList -join ','), deliveryOption=$DeliveryOption"
|
||||
Reference in New Issue
Block a user