Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0b25fa88d7 |
+2
-456
@@ -27,86 +27,6 @@ info:
|
||||
{sessionId} - you will get this form /mobile/auth method
|
||||
{sessionSecret} - you will get this form /mobile/auth method
|
||||
the last one (x-hrbox-embed) is for opening web pages in WebView to remove website footer and header
|
||||
|
||||
---
|
||||
|
||||
# Авторизация по личному API-токену (Personal Access Token, PAT)
|
||||
|
||||
Для серверных интеграций (web-zaim и т.п.) удобнее не держать сессию,
|
||||
а использовать постоянный токен. Токен работает **только на `/api/v2/*`**
|
||||
(для `/api/v1/*`, `/api/v3/*`, `/admin/*` и веб-страниц — игнорируется).
|
||||
|
||||
## Получение токена
|
||||
|
||||
1. Юзеру, от имени которого будет работать интеграция, нужно право
|
||||
`api-tokens-manage` (выдаётся точечно администратором).
|
||||
2. Юзер открывает `/profile/settings/api-tokens` в веб-интерфейсе и жмёт
|
||||
«Создать токен» — задаёт название и (опционально) дату истечения.
|
||||
Plain-секрет **показывается один раз** в этом окне, после закрытия
|
||||
восстановить нельзя.
|
||||
3. Альтернативно — `POST /api/v2/user-api-token` под session-авторизацией
|
||||
(см. ниже про management-эндпоинты). Plain также возвращается
|
||||
один раз в поле `data.plain`.
|
||||
|
||||
Формат plain-токена: `hrb_` + 32 url-safe символов = 36 символов всего.
|
||||
В БД хранится только HMAC-SHA-256 хеш и видимый префикс (первые 12
|
||||
символов с `hrb_`).
|
||||
|
||||
## Использование токена
|
||||
|
||||
Подписывайте каждый запрос заголовком `Authorization`:
|
||||
|
||||
```
|
||||
Authorization: Bearer hrb_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
|
||||
```
|
||||
|
||||
Tenant авторезолвится по `Host`-заголовку запроса, поэтому
|
||||
`x-hrbox-tenant-id` / `x-hrbox-tenant-domain` **необязательны**.
|
||||
Если всё же передаёте — будут строго провалидированы, невалидный
|
||||
идентификатор тенанта → 400. `x-hrbox-session-id` / `x-hrbox-session-code`
|
||||
при Bearer-аутентификации **не нужны**.
|
||||
|
||||
## Права и scopes
|
||||
|
||||
⚠️ **Гранулярных scopes у токена нет.** Токен наследует **все права того
|
||||
юзера**, под которым выпущен. Это означает что для интеграции нужно
|
||||
создать **отдельного системного пользователя** и выдать ему ровно те
|
||||
права, которые требуются (например, `wallets-transactions` для нового
|
||||
`/api/v2/admin/wallet*`). Не используйте свой личный аккаунт.
|
||||
|
||||
## Отзыв и жизненный цикл
|
||||
|
||||
- Юзер отзывает свой токен через `POST /api/v2/user-api-token/revoke`
|
||||
(или из UI).
|
||||
- Администратор с правом `api-tokens-admin` может посмотреть/отозвать
|
||||
любой токен тенанта через `/api/v2/admin/user-api-token*`. Plain
|
||||
админу **никогда не виден**, только префикс.
|
||||
- При блокировке юзера (`reg_status_id = BLOCKED`) все его токены
|
||||
автоматически отзываются. При разблокировке **обратно не восстанавливаются** —
|
||||
нужно выпускать новые.
|
||||
- Если у токена выставлен `expires_at` — после этой даты он перестаёт
|
||||
работать сам (статус `EXPIRED`).
|
||||
|
||||
## Когда валидный токен всё равно даёт 401
|
||||
|
||||
`User::findIdentityByAccessToken` дополнительно вызывает
|
||||
`User::isValidForDisplay()`, поэтому даже корректный live-токен
|
||||
отдаёт `401 Login Required`, если у владельца:
|
||||
|
||||
- `is_hidden = true` (юзер скрыт администратором), либо
|
||||
- `reg_status_id` **не входит** в `RegStatus::validForDisplay()`
|
||||
(например `INVITED`, `BLOCKED` и пр.).
|
||||
|
||||
Для системного юзера-интегратора убедитесь, что он `is_hidden=false`
|
||||
и в активном reg-статусе, иначе токен не пройдёт ни на одном
|
||||
`/api/v2/*` эндпоинте.
|
||||
|
||||
## Управление токенами под Bearer запрещено
|
||||
|
||||
Management-эндпоинты (`/user-api-token*`, `/admin/user-api-token*`)
|
||||
отдают `403`, если запрос аутентифицирован Bearer-токеном — нельзя
|
||||
выпускать или отзывать токены от имени токена. Управляйте только
|
||||
под обычной web-сессией.
|
||||
contact:
|
||||
email: yuriy@hrbox.io
|
||||
|
||||
@@ -147,16 +67,6 @@ tags:
|
||||
description: Админский API транзакций кошелька — проведение начислений/списаний (form/excel) и просмотр.
|
||||
- name: file-processing
|
||||
description: Статусы асинхронных обработок файлов (excel-импорт/экспорт, архивы). Видны только записи текущего пользователя.
|
||||
- name: user-api-token
|
||||
description: |
|
||||
Личные API-токены (Personal Access Tokens) для серверных интеграций.
|
||||
Юзер управляет только своими токенами. Permission `api-tokens-manage`.
|
||||
Management-эндпоинты доступны **только под обычной session-авторизацией**
|
||||
(Bearer запрещён). См. секцию «Авторизация по личному API-токену» выше.
|
||||
- name: admin-user-api-token
|
||||
description: |
|
||||
Админский обзор и отзыв любых PAT тенанта. Permission `api-tokens-admin`.
|
||||
Plain-секрет недоступен — виден только `token_prefix`.
|
||||
|
||||
paths:
|
||||
/mobile/bind/{id}/{token}:
|
||||
@@ -7355,201 +7265,6 @@ paths:
|
||||
schema:
|
||||
$ref: '#/components/schemas/FileProcessing'
|
||||
|
||||
/user-api-token:
|
||||
get:
|
||||
tags: [user-api-token]
|
||||
summary: Список своих API-токенов
|
||||
description: |
|
||||
Возвращает PAT текущего юзера. Plain-секрет уже недоступен —
|
||||
для идентификации используется `token_prefix` (первые 12 символов,
|
||||
начинаются с `hrb_`).
|
||||
operationId: userApiTokenIndex
|
||||
security:
|
||||
- SessionAuth: []
|
||||
parameters:
|
||||
- name: page
|
||||
in: query
|
||||
schema: { type: integer, minimum: 1, default: 1 }
|
||||
- name: per-page
|
||||
in: query
|
||||
schema: { type: integer, minimum: 1, default: 20 }
|
||||
- name: sort
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [created_at, "-created_at", last_used_at, "-last_used_at", expires_at, "-expires_at"]
|
||||
description: По умолчанию `-created_at`.
|
||||
responses:
|
||||
200:
|
||||
description: Список токенов
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserApiTokenList'
|
||||
403:
|
||||
description: Запрос пришёл под Bearer-токеном (запрещено) или нет права `api-tokens-manage`.
|
||||
|
||||
/user-api-token/create:
|
||||
post:
|
||||
tags: [user-api-token]
|
||||
summary: Создать новый API-токен (plain возвращается один раз)
|
||||
description: |
|
||||
Создаёт PAT для текущего юзера. **Plain-секрет (`data.plain`)
|
||||
возвращается только в этом ответе и больше нигде не доступен** —
|
||||
сохраните его сразу.
|
||||
|
||||
`expires_at` опционален; если задан, должен быть не в прошлом
|
||||
(валидируется по началу текущего дня). Токен работает весь
|
||||
указанный день включительно (23:59:59).
|
||||
|
||||
Доступно только под session-авторизацией (запрос под Bearer → 403).
|
||||
operationId: userApiTokenCreate
|
||||
security:
|
||||
- SessionAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserApiTokenCreateForm'
|
||||
responses:
|
||||
200:
|
||||
description: Токен создан (либо ошибки валидации в стандартном формате `httpJsonResponse`).
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/httpJsonResponse'
|
||||
- type: object
|
||||
properties:
|
||||
data:
|
||||
$ref: '#/components/schemas/UserApiTokenCreated'
|
||||
403:
|
||||
description: Запрос пришёл под Bearer-токеном или нет права `api-tokens-manage`.
|
||||
|
||||
/user-api-token/revoke:
|
||||
post:
|
||||
tags: [user-api-token]
|
||||
summary: Отозвать свой API-токен
|
||||
description: |
|
||||
Идемпотентно: повторный revoke уже отозванного токена просто ничего не делает.
|
||||
Чужой токен отозвать нельзя — будет 403/404.
|
||||
|
||||
Доступно только под session-авторизацией (запрос под Bearer → 403).
|
||||
operationId: userApiTokenRevoke
|
||||
security:
|
||||
- SessionAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [id]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Успех
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/httpJsonResponse'
|
||||
400:
|
||||
description: Параметр `id` не строка или не uuid.
|
||||
403:
|
||||
description: Токен принадлежит другому юзеру, либо запрос под Bearer, либо нет права `api-tokens-manage`.
|
||||
404:
|
||||
description: Токен не найден.
|
||||
|
||||
/admin/user-api-token:
|
||||
get:
|
||||
tags: [admin-user-api-token]
|
||||
summary: Список API-токенов всех юзеров тенанта
|
||||
description: |
|
||||
Админский обзор PAT. Permission `api-tokens-admin`. Plain-секрет
|
||||
здесь **никогда не возвращается** (только `token_prefix`).
|
||||
|
||||
Доступно только под session-авторизацией (запрос под Bearer → 403).
|
||||
operationId: adminUserApiTokenIndex
|
||||
security:
|
||||
- SessionAuth: []
|
||||
parameters:
|
||||
- name: page
|
||||
in: query
|
||||
schema: { type: integer, minimum: 1, default: 1 }
|
||||
- name: per-page
|
||||
in: query
|
||||
schema: { type: integer, minimum: 1, default: 20 }
|
||||
- name: sort
|
||||
in: query
|
||||
schema:
|
||||
type: string
|
||||
enum: [created_at, "-created_at", last_used_at, "-last_used_at", expires_at, "-expires_at"]
|
||||
- name: user_id
|
||||
in: query
|
||||
schema: { type: string, format: uuid }
|
||||
description: Фильтр по владельцу токена.
|
||||
- name: name
|
||||
in: query
|
||||
schema: { type: string, maxLength: 100 }
|
||||
description: Like-поиск по названию токена.
|
||||
- name: token_prefix
|
||||
in: query
|
||||
schema: { type: string, maxLength: 16 }
|
||||
description: 'Like-поиск по префиксу (например `hrb_abc12345`).'
|
||||
- name: status_id
|
||||
in: query
|
||||
schema: { type: string }
|
||||
description: |
|
||||
Comma-separated `UserApiTokenStatus`: `1` — Активен, `2` — Отозван,
|
||||
`3` — Истёк. Без параметра — все статусы.
|
||||
responses:
|
||||
200:
|
||||
description: Список
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/UserApiTokenAdminList'
|
||||
403:
|
||||
description: Запрос под Bearer, либо нет права `api-tokens-admin`.
|
||||
|
||||
/admin/user-api-token/revoke:
|
||||
post:
|
||||
tags: [admin-user-api-token]
|
||||
summary: Отозвать любой токен тенанта
|
||||
description: |
|
||||
Идемпотентно. Доступно только под session-авторизацией (Bearer → 403).
|
||||
operationId: adminUserApiTokenRevoke
|
||||
security:
|
||||
- SessionAuth: []
|
||||
requestBody:
|
||||
required: true
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
required: [id]
|
||||
properties:
|
||||
id:
|
||||
type: string
|
||||
format: uuid
|
||||
responses:
|
||||
200:
|
||||
description: Успех
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
$ref: '#/components/schemas/httpJsonResponse'
|
||||
400:
|
||||
description: Параметр `id` не строка или не uuid.
|
||||
403:
|
||||
description: Запрос под Bearer, либо нет права `api-tokens-admin`.
|
||||
404:
|
||||
description: Токен не найден.
|
||||
|
||||
components:
|
||||
securitySchemes:
|
||||
SessionAuth:
|
||||
@@ -7562,16 +7277,6 @@ components:
|
||||
in: header
|
||||
name: X-Hrbox-Client-Id
|
||||
description: "Авторизация с использованием API-ключа. Требуемые заголовки: Content-Type, X-Hrbox-Client-Id, X-Hrbox-Client-Secret."
|
||||
BearerAuth:
|
||||
type: http
|
||||
scheme: bearer
|
||||
bearerFormat: PAT
|
||||
description: |
|
||||
Personal Access Token (постоянный API-токен пользователя). Заголовок:
|
||||
`Authorization: Bearer hrb_<32 url-safe>`. Tenant авторезолвится по
|
||||
`Host`, `x-hrbox-tenant-id` опционален. Работает только на `/api/v2/*`.
|
||||
Токен наследует все права юзера, под которым выпущен (granular scopes
|
||||
не поддерживаются). Подробности — в описании API.
|
||||
schemas:
|
||||
httpJsonResponse:
|
||||
type: object
|
||||
@@ -12379,8 +12084,6 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/Wallet'
|
||||
_links:
|
||||
$ref: '#/components/schemas/_links'
|
||||
_meta:
|
||||
$ref: '#/components/schemas/_meta'
|
||||
|
||||
@@ -12413,8 +12116,6 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/WalletTransaction'
|
||||
_links:
|
||||
$ref: '#/components/schemas/_links'
|
||||
_meta:
|
||||
$ref: '#/components/schemas/_meta'
|
||||
|
||||
@@ -12494,13 +12195,10 @@ components:
|
||||
1 — NEW, 2 — QUEUED, 3 — STARTED, 4 — FINISHED, 5 — ERROR, 6 — FATAL
|
||||
arguments:
|
||||
type: array
|
||||
description: |
|
||||
Аргументы воркера. Для wallet-excel: `[WalletExcelProcessor::class, mappings]`.
|
||||
Для excel-экспорта: `[ReportClass::class, params]`.
|
||||
items: {}
|
||||
result:
|
||||
type: object
|
||||
description: |
|
||||
Результат. Для wallet-excel:
|
||||
Результат. Для wallet-excel содержит:
|
||||
```
|
||||
{
|
||||
"summary": { "totalRows": 4, "validCount": 1, "invalidCount": 3 },
|
||||
@@ -12508,32 +12206,9 @@ components:
|
||||
"invalidRows": [{ "row": 2, "errors": {...} }, ...]
|
||||
}
|
||||
```
|
||||
Для незавершённой обработки или экспорта — пустой массив `[]`.
|
||||
oneOf:
|
||||
- type: object
|
||||
- type: array
|
||||
items: {}
|
||||
created_at: { type: string }
|
||||
started_at: { type: string, nullable: true }
|
||||
finished_at: { type: string, nullable: true }
|
||||
file:
|
||||
type: object
|
||||
nullable: true
|
||||
description: |
|
||||
Метаданные файла-источника. Возвращается всегда (не нужно `?expand=`).
|
||||
Содержит `id, name, ext, fid, url, file_type, mime_type, size,
|
||||
file_status_id, user_id, created_at` и др.
|
||||
created:
|
||||
type: string
|
||||
description: 'Локализованная `created_at` (например `04.05.2026 at 13:56`).'
|
||||
started:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Локализованная `started_at`.
|
||||
finished:
|
||||
type: string
|
||||
nullable: true
|
||||
description: Локализованная `finished_at`.
|
||||
|
||||
FileProcessingList:
|
||||
type: object
|
||||
@@ -12542,134 +12217,6 @@ components:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/FileProcessing'
|
||||
_links:
|
||||
$ref: '#/components/schemas/_links'
|
||||
_meta:
|
||||
$ref: '#/components/schemas/_meta'
|
||||
|
||||
UserApiTokenStatus:
|
||||
type: integer
|
||||
description: |
|
||||
Статус личного API-токена (вычисляется по `revoked_at` / `expires_at`):
|
||||
* `1` — Активен
|
||||
* `2` — Отозван
|
||||
* `3` — Истёк
|
||||
enum: [1, 2, 3]
|
||||
example: 1
|
||||
|
||||
UserApiToken:
|
||||
type: object
|
||||
description: |
|
||||
Личный API-токен (PAT). Plain-секрет в этой схеме отсутствует — он
|
||||
возвращается только в ответе на создание (см. `UserApiTokenCreated`).
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
user_id: { type: string, format: uuid }
|
||||
name:
|
||||
type: string
|
||||
maxLength: 100
|
||||
description: Человекочитаемое название от юзера (HTML-теги вырезаются на бэке).
|
||||
token_prefix:
|
||||
type: string
|
||||
description: |
|
||||
Первые 12 символов токена с приставкой `hrb_`. Безопасно для отображения
|
||||
и поиска (например `hrb_abc12345`).
|
||||
example: "hrb_abc12345"
|
||||
created_at: { type: string, format: date-time }
|
||||
expires_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: Если null — без срока. Срок включает указанный день целиком (до 23:59:59).
|
||||
last_used_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: Обновляется при использовании, не чаще раза в минуту.
|
||||
revoked_at:
|
||||
type: string
|
||||
format: date-time
|
||||
nullable: true
|
||||
description: Заполняется при revoke; если null — токен не отозван.
|
||||
|
||||
UserApiTokenList:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UserApiToken'
|
||||
_links:
|
||||
$ref: '#/components/schemas/_links'
|
||||
_meta:
|
||||
$ref: '#/components/schemas/_meta'
|
||||
|
||||
UserApiTokenCreated:
|
||||
description: |
|
||||
Расширение `UserApiToken` дополнительным полем `plain` — это
|
||||
единственный момент, когда секрет возвращается клиенту.
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/UserApiToken'
|
||||
- type: object
|
||||
required: [plain]
|
||||
properties:
|
||||
plain:
|
||||
type: string
|
||||
description: |
|
||||
Полный plain-токен. Формат `hrb_<32 url-safe>`. **Сохраните
|
||||
немедленно — повторно его получить невозможно.**
|
||||
example: "hrb_aBcD3fGhIjKlMnOpQrStUvWxYz012345"
|
||||
|
||||
UserApiTokenCreateForm:
|
||||
type: object
|
||||
required: [name]
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
maxLength: 100
|
||||
description: Название токена. Сохраняется после HTML-purify.
|
||||
example: "Интеграция web-zaim — wallet"
|
||||
expires_at:
|
||||
type: string
|
||||
format: date
|
||||
nullable: true
|
||||
description: |
|
||||
Дата истечения `yyyy-MM-dd`. Не может быть в прошлом (валидируется
|
||||
по началу текущего дня). На бэке к ней приклеивается время
|
||||
`23:59:59`, токен работает весь указанный день включительно.
|
||||
Если опущено — токен бессрочный.
|
||||
example: "2026-12-31"
|
||||
|
||||
UserApiTokenAdmin:
|
||||
description: |
|
||||
Запись токена в админском списке: к базовым полям добавляются вложенные
|
||||
`user` и `updatedByUser` (последний — кто последним менял запись;
|
||||
для авто-revoke при блокировке — система).
|
||||
allOf:
|
||||
- $ref: '#/components/schemas/UserApiToken'
|
||||
- type: object
|
||||
properties:
|
||||
user:
|
||||
type: object
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
name: { type: string }
|
||||
updatedByUser:
|
||||
type: object
|
||||
nullable: true
|
||||
properties:
|
||||
id: { type: string, format: uuid }
|
||||
name: { type: string }
|
||||
|
||||
UserApiTokenAdminList:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/UserApiTokenAdmin'
|
||||
_links:
|
||||
$ref: '#/components/schemas/_links'
|
||||
_meta:
|
||||
$ref: '#/components/schemas/_meta'
|
||||
|
||||
@@ -12859,4 +12406,3 @@ components:
|
||||
security:
|
||||
- SessionAuth: [ ]
|
||||
- ApiKeyAuth: [ ]
|
||||
- BearerAuth: [ ]
|
||||
Reference in New Issue
Block a user