rest api: accept Basic Auth with the panel password for writes

Any login, password = web/settings password (or master password). 401
carries WWW-Authenticate so browsers/Postman prompt. X-Api-Key still
works for existing integrations. Docs warn that over plain HTTP the
password travels in every request.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-10 10:58:05 +00:00
co-authored by Claude Opus 5.5
parent 392095d549
commit ec84133417
3 changed files with 54 additions and 28 deletions
+23 -12
View File
@@ -2,7 +2,18 @@
Базовый адрес — тот же, что у веб-конфигуратора (по умолчанию порт 8080). Отдельного процесса нет.
Чтение открыто. Запись требует заголовок `X-Api-Key`. Ключ лежит в `settings.apiKey`, создаётся сам при первом запуске и показывается на вкладке «Безопасность» конфигуратора. Запроса «отдать ключ» в этом API нет: его увидел бы любой в сети. Неверный или пустой ключ — HTTP 401:
Чтение открыто. Запись требует авторизацию, подходит любой из двух способов:
- **Basic Auth с паролем веб-панели** (основной способ). Логин любой, например `admin`; пароль тот же, что для входа в конфигуратор и настройки на экране (подходит и мастер-пароль). Сменили пароль в панели — меняется и пароль для API.
```sh
curl -u admin:ПАРОЛЬ -X POST http://<ip>:8080/api/v1/buttons/<id>/press
```
- **Заголовок `X-Api-Key`** (оставлен для уже настроенных интеграций). Ключ лежит в `settings.apiKey` и показывается на вкладке «Безопасность» конфигуратора.
Устройство работает по HTTP, поэтому пароль в Basic Auth передаётся по сети открытым текстом в каждом запросе (так же, как при входе в веб-панель). Кто перехватит трафик, получит пароль администратора, а с ним и OTA, то есть root на устройстве. Ключ API при утечке даёт меньше: только методы записи API. В доверенной сети это приемлемо; если интеграция ходит через чужую сеть, лучше ключ.
Без авторизации или с неверными данными — HTTP 401 с заголовком `WWW-Authenticate: Basic`:
```json
{ "ok": false, "error": "unauthorized" }
@@ -111,7 +122,7 @@
## PUT /api/v1/sensors/{mac}/name
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
```json
{ "name": "Резервуар_1" }
@@ -136,7 +147,7 @@
## PUT /api/v1/settings
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Принимается только `report_interval_min`, целое от 1 до 65535. Иначе HTTP 400 `invalid_interval`. `stale_timeout_s` записать нельзя.
@@ -154,7 +165,7 @@
## PUT /api/v1/sensors/{mac}/calibration
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
```json
{ "empty_mm": 1200, "full_mm": 200 }
@@ -178,7 +189,7 @@
## GET /api/v1/buttons/{id}
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Полная карточка кнопки: подпись, иконка, действие, тексты ответа, удержание и цвет. Неизвестный id — HTTP 404 `button_not_found`.
@@ -206,7 +217,7 @@
## POST /api/v1/buttons
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Создаёт кнопку. Идентификатор назначается сам. Поля те же, что при правке, плюс плоские имена действия: `actionType` (`http_get` или `http_post`), `url`, `headers`, `body`, `timeoutMs` (1000…600000), `successText`, `errorText`, `pendingText`, `fadeMs`, `triggerMode` (`click` или `hold`), `holdMs`, `color`, `iconPath`, `latchReset`, `responseCheck`. Некорректное тело — HTTP 400 `invalid_button` и поле `message` с причиной. Ответ HTTP 201 — созданная карточка.
@@ -223,13 +234,13 @@
## PUT /api/v1/buttons/{id}
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Меняет только переданные поля. Имена полей те же, что у создания. Неизвестный id — HTTP 404 `button_not_found`. Некорректное поле — HTTP 400 `invalid_button`. Ответ — карточка после записи. Экран подхватывает конфиг сам.
## DELETE /api/v1/buttons/{id}
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Удаляет кнопку. Неизвестный id — HTTP 404 `button_not_found`.
@@ -239,7 +250,7 @@
## POST /api/v1/buttons/reorder
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Порядок кнопок на экране. В `order` — идентификаторы спереди назад. Пропущенные остаются в конце в прежнем порядке. `order` не массив строк — HTTP 400 `invalid_order`.
@@ -271,7 +282,7 @@
## PUT /api/v1/background
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Меняет только переданные поля. Цвет — `#rrggbb`. `animated` — логическое. Иначе HTTP 400 `invalid_background`. Ответ — фон после записи.
@@ -286,7 +297,7 @@
## POST /api/v1/buttons/{id}/press
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
То же действие, что нажатие на экране, включая защёлку. Тело не нужно.
@@ -300,7 +311,7 @@
## POST /api/v1/system/reboot
Заголовок `X-Api-Key` обязателен.
Нужна авторизация (Basic или `X-Api-Key`, см. начало).
Перезагрузка устройства тем же путём, что кнопка в конфигураторе. Ответ уходит до того, как машина погаснет.