Роли и права
> Кратко. Права пользователя — это шаблон роли плюс отличия, которые администратор отметил галочками. Сервер проверяет права на каждом запросе сам, веб только прячет недоступные кнопки. Поверх прав действуют флаги сервера: без MUTATIONSENABLED данные нельзя менять никому, включая администратора.
Как выдавать роли и права в окне, описано на странице Пользователи. Здесь — модель прав и настройки сервера.
Матрица «вид объекта × действие»
Для каждой пары задаётся охват: нет, только свои или все.
| Вид объекта | Свойства | Создание | Перемещение и изломы | Удаление |
|---|---|---|---|---|
| Участки | ✓ | ✓ | ✓ | ✓ |
| Узлы | ✓ | ✓ | ✓ | ✓ |
| Потребители | ✓ | ✓ | ✓ | ✓ |
| Источники и насосные станции | ✓ | ✓ | ✓ | ✓ |
| Оборудование | ✓ | ✓ | — | ✓ |
| Режим узла (заданный напор, подпитка) | ✓ | — | — | — |
Оборудование стоит на линии и отдельно не перемещается, режим узла только правится. Создание бывает «нет» или «все»: «создавать только свои» не имеет смысла.
«Только свои». Своими считаются объекты, которые пользователь создал в вебе. Авторство пишется в таблицу
object_authorship базы города при сохранении правки. Строка карточки (оборудование, потребитель) своя, если свой её
участок или узел. Объекты из десктопа и созданные до 20.10.2026 ничьи. С охватом «только свои» их нельзя ни
править, ни удалять. Отказ называет чужие объекты: «Можно только со своими объектами, а это не ваши: …».
Общие права
| Право | Подпись в окне |
|---|---|
calc_run |
Запуск расчётов |
calc_save |
Сохранение и сравнение расчётов, направления пьезометра |
export |
Выгрузки и отчёты |
import |
Импорт сети |
journals |
Журналы: ремонты, ПТС, акты, ТУ, привязки |
refs |
Справочники и шаблоны карточек |
audit_view |
Просмотр журнала действий |
users_admin |
Управление пользователями |
pii_view |
Персональные данные потребителей полностью (ФИО, телефоны, счета) |
Шаблоны ролей
| Роль | Сеть | Общие права |
|---|---|---|
Просмотр (viewer) |
ничего | выгрузки |
Режимщик (calculator) |
свойства потребителей, источников, оборудования и режим узлов — все | расчёты, сохранение расчётов, выгрузки |
Оператор сети (operator) |
создание — все; свойства, перемещение, удаление — только свои | выгрузки |
Редактор (editor) |
свойства, создание, перемещение — все; удаление — только свои | расчёты, сохранение, выгрузки, импорт, журналы, справочники, ПДн |
Администратор (admin) |
всё — все | все права |
В UsersDB хранятся только отличия пользователя от шаблона (users.permissions, JSON): действующие права — шаблон
роли плюс эти отличия. Их веб получает из /api/v1/auth/me.
Применить импорт сети может только администратор, даже если у другой роли есть право «Импорт сети»: с этим правом доступен лишь предпросмотр.
Защита от потери доступа: нельзя снять роль администратора с себя или заблокировать себя. Последнего активного администратора нельзя понизить или заблокировать, пока не настроена мастер-учётка.
Мастер-учётка
Учётная запись владельца вне UsersDB. Она нужна для первого входа на пустую базу пользователей и на случай, если все администраторы заблокированы.
- Логин —
MASTER_LOGIN(по умолчаниюadmin), пароль — хеш bcrypt вMASTER_PASSWORD_HASH. Пока хеш не задан, мастер-учётки нет. - Её логин занят: пользователя UsersDB с таким логином завести нельзя. Ей доступны все города, роль — администратор.
- Из веба её нельзя удалить, заблокировать или сменить ей пароль: смена пароля в кабинете отвечает 409. Пароль
меняют на сервере: записывают новый хеш в
.envAPI и перезапускают API. - В токене мастер-учётки хранится отпечаток хеша. Новый хеш закрывает все её прежние сессии.
- Хеш содержит символ
$, поэтому в.envего пишут в одинарных кавычках.
Получить хеш можно функцией auth.hash_password из каталога API (venv\Scripts\python.exe, пароль вводится
через getpass и в командную строку не попадает). Первого администратора UsersDB без мастер-учётки создаёт
scripts/create_user.py <логин> --role admin. Пароль скрипт берёт из TGID_NEW_PASSWORD или спрашивает.
Флаги сервера
| Флаг | По умолчанию | Что делает |
|---|---|---|
AUTH_DISABLED |
true |
Проверки входа нет: каждый запрос — пользователь dev с ролью администратора. Управление пользователями отвечает 503 «…доступно только при AUTH_DISABLED=false», MCP принимает вызовы без токена. Только для стендов |
AUTH_REQUIRED_GET |
false |
true — без токена закрыто всё, кроме /health, /docs, /openapi.json, /fragments, /russian-names, входа и настроек входа, /metrics, публичной карты отключений и встраиваемой карты. При false чтение данных сети, карточки и расчётные калькуляторы доступны без входа, а GeoServer пускает всех |
STRICT_AUTH |
false |
true — API не стартует при AUTH_DISABLED=true, JWT_SECRET по умолчанию, DEV_LOGIN_ENABLED=true или AUTH_REQUIRED_GET=false |
DEV_LOGIN_ENABLED |
false |
Вход с любым логином и любой ролью без пароля. На сервере с доступом извне — никогда |
MUTATIONS_ENABLED |
false |
Без него — 503 на запись данных сети и журналов: карточки, групповая правка, журналы и привязки, наряды, обходы, отключения, телеметрия, водопровод, социальные объекты, сохранение расчёта. Расчёт запускается, если не пишет исходные данные; с сохранением нагрузок потребителей или дросселей (-save_po, -dross_yes) — 503 |
TOPOLOGY_MUTATIONS_ENABLED |
false |
Без него — 503 на правку состава сети: создание, перемещение, удаление, цепочки участков, импорт сети, перенос и слияние фрагментов, сценарии (создание, архив), перспективный сценарий. Нужен ещё MUTATIONS_ENABLED. Предпросмотр правок сети (dry_run) работает и без флага, а предпросмотр импорта сети и переноса фрагментов — нет: он пишет в откатываемой транзакции |
Безопасный набор для сервера с доступом извне: AUTH_DISABLED=false, AUTH_REQUIRED_GET=true, STRICT_AUTH=true,
DEV_LOGIN_ENABLED=false и собственный длинный JWT_SECRET.
MUTATIONS_ENABLED не блокирует то, что не меняет данные сети: управление пользователями, ключи встраивания,
ключи API v2, ArcGIS и MCP, вебхуки, комментарии на карте, короткие ссылки, сохранённые стили слоёв и конфигурации
трассировки. Эти действия проверяются только правами.
Текущие флаги видны без входа: GET /api/v1/auth/config и поле flags ответа /health. В вебе выключенная запись
прячет или выключает кнопки (useMutationsEnabled). В подсказках части окон при этом показывается имя настройки,
например «Запись выключена на сервере (MUTATIONS_ENABLED)».
Вход и сессии
- Сессия — JWT на
JWT_EXPIRE_MINUTES(по умолчанию 480 мин). Блокировка, смена роли и городов действуют на выданные токены через живую сверку с UsersDB (кешUSER_STATUS_TTL, 30 с). - После 5 неудачных входов на логин или 30 с одного адреса за 10 минут вход временно закрыт (429). Адрес берётся
из
CF-Connecting-IP, иначе из адреса соединения. - Удачные и неудачные входы, выходы и смена пароля пишутся в журнал действий.
Роли PostgreSQL
При AUTH_BACKEND=pg пользователи — роли PostgreSQL tgid_u_* с паролем, как в десктопе. Права на сеть они
получают только из предметных прав (tgid_cap_network — свойства, tgid_cap_network_struct — состав сети
и импорт). Журналы, справочники и ПДн — по правам pts, repairs, acts, corrosion, geo. Администратор
получает всё. DB_ROLE_SWITCH=true ставит роль пользователя на каждое соединение: права проверяет ещё и сам
PostgreSQL. Подробности — docs/pg-auth.md в репозитории API.
Для разработчика
- Модель —
permissions.py(KINDS,ACTIONS,GENERAL,ROLE_PRESETS,effective); в вебе шаблоны повторены вutils/permissions.ts. Новое право или роль меняют в обоих местах. - Новый маршрут записи — через
require_permission(...)или проверку_guard/ensure_targetsс охватом «свои», а не черезrequire_roles. Плюсrequire_mutations_enabled()(илиrequire_topology_mutations_enabled()для состава сети). - Флаги —
auth.py(auth_disabled,mutations_enabled,auth_required_get,assert_production_auth_safe), обязательный вход —AuthRequiredGetMiddlewareвmain.py.
