netpulse-migrate замість PowerShell-скрипта: у контейнері немає ані psql, ані PowerShell, а тягнути клієнт Postgres в образ заради одного запуску — це половина дистрибутива на порожньому місці. Міграції вшиті через embed і переїхали в server/migrations: embed не бачить нічого за межами кореня свого модуля, а міграції поруч із бінарником, який їх накочує, не можуть розійтися версіями. Накочування під advisory-блокуванням: два інстанси при rolling update інакше застосували б ту саму міграцію двічі. Кожен файл в одній транзакції разом із записом у schema_migrations; виняток — continuous aggregates, які TimescaleDB забороняє в транзакції. Змінена вже застосована міграція зупиняє запуск: у різних інсталяціях інакше опиниться різна схема під одним номером. Перевірено на чистій базі: 23 міграції, 101 таблиця, повторний запуск каже «схема актуальна». Веб віддає сам API через embed: на self-hosted це прибирає з інструкції встановлення цілий компонент. Три політики кешування — назавжди для assets із хешем у імені, ніколи для index.html, коротко для решти. Знайдено живим прогоном: невідомий шлях під /api/ віддавав 200 з index.html, і клієнт падав на розборі HTML як JSON замість чесного 404. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
30 lines
1.5 KiB
SQL
30 lines
1.5 KiB
SQL
-- =====================================================================
|
||
-- NetPulse :: 0020_dashboard_perms.sql
|
||
-- Права на дашборди.
|
||
--
|
||
-- Окремі від maps:* навмисно: дашборд збирає дані з усього тенанта, і
|
||
-- «може дивитись мапу» не означає «може дивитись зведення по грошах,
|
||
-- SLA й усіх майданчиках».
|
||
-- =====================================================================
|
||
|
||
INSERT INTO core.permissions (key, description) VALUES
|
||
('dashboards:read', 'Перегляд дашбордів'),
|
||
('dashboards:write', 'Створення та редагування дашбордів')
|
||
ON CONFLICT (key) DO NOTHING;
|
||
|
||
-- Видають тим, хто вже має відповідний рівень доступу до мап: набір
|
||
-- ролей у продукті один, і розводити їх тут означало б завести роль,
|
||
-- яка бачить мапу й не бачить дашборда з тією ж мапою всередині.
|
||
INSERT INTO core.role_permissions (role_id, permission_key)
|
||
SELECT rp.role_id, 'dashboards:read'
|
||
FROM core.role_permissions rp
|
||
WHERE rp.permission_key = 'maps:read'
|
||
ON CONFLICT DO NOTHING;
|
||
|
||
INSERT INTO core.role_permissions (role_id, permission_key)
|
||
SELECT rp.role_id, 'dashboards:write'
|
||
FROM core.role_permissions rp
|
||
WHERE rp.permission_key = 'maps:write'
|
||
ON CONFLICT DO NOTHING;
|
||
|
||
-- Роль із «*» уже покриває все — її не чіпаємо.
|