feat: вебхук-подписка новых списков в провизионере
Tests / frontend-test (push) Successful in 1m13s

This commit is contained in:
Тимур Городецкий
2026-09-25 10:08:08 +05:00
parent ec94de3c1b
commit 6712d050a5
2 changed files with 76 additions and 2 deletions
+60 -1
View File
@@ -61,6 +61,15 @@
.PARAMETER SkipRename
Не выполнять миграцию имён существующих списков (только создание/колонки).
.PARAMETER WebhookToken
Bearer-токен Microsoft (JWT, без слова «Bearer») для api.tnsu.kz. Если задан — на
КАЖДЫЙ НОВЫЙ список (и «— данные», и «— согласование») оформляется вебхук-подписка
через POST https://api.tnsu.kz/Webhook/Subscribe: бэкенд подписывается на изменения
в списке, уведомления идут на https://api.tnsu.kz/Webhook/SharePoint. Уже
существующие списки не подписываются. Не задан — списки создаются как раньше, по
каждому новому выводится предупреждение (подписать вручную). Токен живёт ~1 час —
берите свежий перед запуском. В коде и репозитории токен не хранится.
.EXAMPLE
./Provision-Lists.ps1 -SiteUrl "https://tnsukz.sharepoint.com/sites/requests" `
-ClientId "7459c965-5ed4-4673-8140-0ab8faf9db64" -Tenant "tnsukz.onmicrosoft.com" `
@@ -70,6 +79,11 @@
# Следующая пара списков под архивацию, без миграции имён.
./Provision-Lists.ps1 -SiteUrl "..." -ClientId "..." -Tenant "..." -Thumbprint "..." `
-ListNumber 2
.EXAMPLE
# С вебхук-подпиской новых списков.
./Provision-Lists.ps1 -SiteUrl "..." -ClientId "..." -Tenant "..." -Thumbprint "..." `
-WebhookToken "eyJ0eXAiOiJKV1Qi..."
#>
param(
[Parameter(Mandatory = $true)][string]$SiteUrl,
@@ -78,11 +92,16 @@ param(
[Parameter(Mandatory = $true)][string]$Thumbprint,
[string]$FormsRoot = "$PSScriptRoot/../src/webparts/requestPortal/forms",
[ValidateRange(1, 999)][int]$ListNumber = 1,
[switch]$SkipRename
[switch]$SkipRename,
[string]$WebhookToken
)
$ErrorActionPreference = 'Stop'
# Вебхук-подписка новых списков (см. .PARAMETER WebhookToken).
$WEBHOOK_SUBSCRIBE_URL = 'https://api.tnsu.kz/Webhook/Subscribe'
$WEBHOOK_NOTIFICATION_URL = 'https://api.tnsu.kz/Webhook/SharePoint'
# Экранирование значений, попадающих в XML полей (Lookup/Number с точностью).
function ConvertTo-XmlSafe {
param([string]$Value)
@@ -306,6 +325,34 @@ function Add-ColumnToList {
}
}
# Оформляет вебхук-подписку на список через бэкенд api.tnsu.kz. Ошибка подписки
# провизионинг НЕ останавливает: список уже создан, подписать можно и вручную.
function Register-ListWebhook {
param([string]$ListTitle)
if (-not $WebhookToken) {
Write-Warning " [!] вебхук: «$ListTitle» не подписан — не передан -WebhookToken, подпишите список вручную"
return
}
# Токен могли вставить вместе со словом «Bearer» — убираем, иначе заголовок сломается.
$token = ($WebhookToken -replace '^\s*Bearer\s+', '').Trim()
$query = @(
"listName=$([uri]::EscapeDataString($ListTitle))",
"url=$([uri]::EscapeDataString($SiteUrl.TrimEnd('/')))",
"notificationUrl=$([uri]::EscapeDataString($WEBHOOK_NOTIFICATION_URL))"
) -join '&'
try {
Invoke-RestMethod -Method Post -Uri "$($WEBHOOK_SUBSCRIBE_URL)?$query" `
-Headers @{ Authorization = "Bearer $token"; Accept = '*/*' } | Out-Null
Write-Host " [+] вебхук: подписан «$ListTitle»" -ForegroundColor Green
}
catch {
Write-Warning " [!] вебхук: «$ListTitle» не подписан — $($_.Exception.Message) (подпишите список вручную)"
}
}
Write-Host "Подключение к $SiteUrl (app-only) ..." -ForegroundColor Cyan
Connect-PnPOnline -Url $SiteUrl -ClientId $ClientId -Tenant $Tenant -Thumbprint $Thumbprint
@@ -357,12 +404,15 @@ if ($ListNumber -eq 1 -and -not $SkipRename) {
# сначала все списки, потом все колонки: к моменту разрешения любого Lookup'а
# список-источник уже существует.
Write-Host "`n=== Списки ===" -ForegroundColor Cyan
# Созданные В ЭТОМ запуске — только их подписываем на вебхук (см. конец скрипта).
$createdLists = [System.Collections.Generic.List[string]]::new()
foreach ($manifest in $manifests) {
$def = Get-Content -Path $manifest.FullName -Raw -Encoding UTF8 | ConvertFrom-Json
$listTitle = Get-NumberedListTitle -Title $def.dataListTitle -Number $ListNumber
if (-not (Get-PnPList -Identity $listTitle -ErrorAction SilentlyContinue)) {
New-PnPList -Title $listTitle -Template GenericList -EnableVersioning | Out-Null
$createdLists.Add($listTitle)
Write-Host " [+] создан список «$listTitle»" -ForegroundColor Green
}
else {
@@ -393,5 +443,14 @@ foreach ($manifest in $manifests) {
}
}
# Проход 3: вебхуки — ПОСЛЕ колонок, чтобы бэкенд подписывался на уже готовый список.
# Только новые списки: существующие подписаны раньше (или вручную).
if ($createdLists.Count -gt 0) {
Write-Host "`n=== Вебхуки новых списков ===" -ForegroundColor Cyan
foreach ($listTitle in $createdLists) {
Register-ListWebhook -ListTitle $listTitle
}
}
Write-Host "`nГотово." -ForegroundColor Cyan
Disconnect-PnPOnline
+16 -1
View File
@@ -21,7 +21,7 @@
| `Text` | однострочный текст | — |
| `Note` | многострочный текст| — |
| `Number` | число | `decimals` (знаков после запятой) |
| `Choice` | выбор из вариантов | `choices` (массив) |
| `Choice` | выбор из вариантов | `choices` (массив), `allowMultiple` (множественный выбор — колонка MultiChoice; тип существующей колонки скрипт не меняет) |
| `DateTime` | дата/время | — |
| `Boolean` | да/нет | — |
| `User` | пользователь | — |
@@ -72,6 +72,21 @@ cd provisioning
Лог: `[+]` — создано, `[=]` — уже существовало, `[~]` — переименовано, `[!]` — предупреждение.
### Вебхук-подписка новых списков
Если передать `-WebhookToken "<JWT>"` (bearer-токен Microsoft для api.tnsu.kz, без
слова «Bearer»), то на каждый список, СОЗДАННЫЙ в этом запуске («— данные» и
«— согласование»), скрипт в конце отправит:
```
POST https://api.tnsu.kz/Webhook/Subscribe?listName=<список>&url=<сайт>&notificationUrl=https://api.tnsu.kz/Webhook/SharePoint
```
Бэкенд подписывается на изменения в списке, уведомления приходят на
`/Webhook/SharePoint`. Существующие списки не подписываются. Без токена или при
ошибке запроса — предупреждение `[!] вебхук: … не подписан` (подписать вручную),
провизионинг при этом не останавливается. Токен живёт ~1 час — берите свежий.
## Важно про имена колонок
В манифесте у колонки два имени: