Files
request-portal/provisioning/README.md
T
Тимур Городецкий 6712d050a5
Tests / frontend-test (push) Successful in 1m13s
feat: вебхук-подписка новых списков в провизионере
2026-09-25 10:08:08 +05:00

103 lines
6.4 KiB
Markdown

# Провижининг списков SharePoint
Автоматическое создание списков **данных** для форм портала заявок из манифестов
`provisioning.json` (по одному на форму, лежат в папке каждой формы).
> Списки **согласования** пока не создаются — только данные.
## Как это работает
- Каждая форма описывает свои колонки в `src/webparts/requestPortal/forms/<Форма>/provisioning.json`.
- Скрипт `Provision-Lists.ps1` читает все такие манифесты и **идемпотентно** создаёт
списки и колонки: перед созданием колонки проверяется, что её ещё нет; повторный
запуск ничего не ломает и не дублирует.
Добавить колонку/форму = отредактировать/добавить `provisioning.json` и перезапустить скрипт.
## Поддерживаемые типы колонок (`type` в манифесте)
| type | Что это | Доп. поля |
| ---------- | ------------------ | --------- |
| `Text` | однострочный текст | — |
| `Note` | многострочный текст| — |
| `Number` | число | `decimals` (знаков после запятой) |
| `Choice` | выбор из вариантов | `choices` (массив), `allowMultiple` (множественный выбор — колонка MultiChoice; тип существующей колонки скрипт не меняет) |
| `DateTime` | дата/время | — |
| `Boolean` | да/нет | — |
| `User` | пользователь | — |
| `Url` | гиперссылка (адрес + подпись) | — |
| `Lookup` | подстановка | `lookupList` (заголовок источника), `lookupShowField` (по умолч. `Title`) |
Плюс на уровне формы: `titleColumnName` — переименовать стандартную колонку `Title`.
> **Порядок для Lookup:** список-источник должен существовать раньше, чем колонка,
> которая на него ссылается — но следить за этим руками не нужно: скрипт сначала
> создаёт ВСЕ списки, и только потом колонки, поэтому порядок обхода манифестов
> не важен (и взаимные ссылки тоже разрешимы).
## Разовая подготовка
1. Установить модуль PnP PowerShell (нужен PowerShell 7+):
```powershell
Install-Module PnP.PowerShell -Scope CurrentUser
```
2. Зарегистрировать приложение с правом `Sites.Selected` и сертификатом в хранилище:
```powershell
Register-PnPEntraIDApp -ApplicationName "PnP-Provisioning-Scoped" -Tenant "<тенант>.onmicrosoft.com" -SharePointApplicationPermissions "Sites.Selected" -Store CurrentUser
```
Запомнить **Client Id** из вывода.
3. Администратор один раз:
- одобряет запрос на согласие приложения (Admin consent),
- выдаёт приложению доступ **только к нужному сайту**:
```powershell
Grant-PnPAzureADAppSitePermission -AppId "<client-id>" -DisplayName "PnP-Provisioning-Scoped" -Permissions FullControl -Site "https://<тенант>.sharepoint.com/sites/<сайт>"
```
## Запуск
Узнать отпечаток сертификата (Thumbprint):
```powershell
Get-ChildItem Cert:\CurrentUser\My | Where-Object { $_.Subject -like "*PnP-Provisioning-Scoped*" } | Select-Object Subject, Thumbprint
```
Запустить провижининг (вход по сертификату, без пароля в коде):
```powershell
cd provisioning
./Provision-Lists.ps1 `
-SiteUrl "https://<тенант>.sharepoint.com/sites/<сайт>" `
-ClientId "<client-id>" `
-Tenant "<тенант>.onmicrosoft.com" `
-Thumbprint "<отпечаток>"
```
Лог: `[+]` — создано, `[=]` — уже существовало, `[~]` — переименовано, `[!]` — предупреждение.
### Вебхук-подписка новых списков
Если передать `-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 час — берите свежий.
## Важно про имена колонок
В манифесте у колонки два имени:
- `internalName` — латиницей, без пробелов, ≤32 символов (техническое имя в SharePoint);
- `title` — отображаемое, любое (рус., с пробелами).
Так мы избегаем проблемы, когда SharePoint кодирует пробелы в `_x0020_` и обращения к
полю ломаются. Не создавайте колонки с русским internalName.
## Проверка на тесте
Сначала прогоните на **тестовом** сайте, убедитесь, что списки и колонки создались
правильно, и только потом — на боевом.