@hubex/mcp 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +54 -0
- package/CONNECTING.md +260 -0
- package/README.md +266 -0
- package/dist/auth.js +226 -0
- package/dist/config.js +120 -0
- package/dist/generated/manifest.js +3643 -0
- package/dist/guides/field-notes.json +27 -0
- package/dist/guides/loader.js +32 -0
- package/dist/guides/service-map.js +6 -0
- package/dist/http.js +93 -0
- package/dist/index/store.js +134 -0
- package/dist/index/types.js +1 -0
- package/dist/index.js +20 -0
- package/dist/paths.js +20 -0
- package/dist/pii/fields.js +100 -0
- package/dist/pii/mask.js +50 -0
- package/dist/pii/strategies.js +88 -0
- package/dist/schema/build-index.js +67 -0
- package/dist/schema/deref.js +87 -0
- package/dist/schema/describe.js +65 -0
- package/dist/server.js +62 -0
- package/dist/token-prompt.js +41 -0
- package/dist/tools/curated.js +151 -0
- package/dist/tools/discovery.js +187 -0
- package/dist/tools/guides.js +126 -0
- package/dist/tools/registry.js +37 -0
- package/dist/tools/request.js +170 -0
- package/dist/tools/types.js +1 -0
- package/docs/guides/assets.md +334 -0
- package/docs/guides/attributes.md +125 -0
- package/docs/guides/checklisttemplates.md +154 -0
- package/docs/guides/companies.md +57 -0
- package/docs/guides/dictionaries.md +64 -0
- package/docs/guides/lifecycle.md +263 -0
- package/docs/guides/materials.md +135 -0
- package/docs/guides/notifications.md +184 -0
- package/docs/guides/roles.md +125 -0
- package/docs/guides/sla.md +130 -0
- package/docs/guides/start.md +67 -0
- package/docs/guides/taskchecklists.md +149 -0
- package/docs/guides/taskcreate.md +260 -0
- package/docs/guides/taskedit.md +277 -0
- package/docs/guides/tasktypes.md +156 -0
- package/docs/guides/users.md +71 -0
- package/generated/index.dev.json +18776 -0
- package/generated/index.prod.json +18858 -0
- package/package.json +48 -0
- package/swagger/dev/ADM.json +27777 -0
- package/swagger/dev/AUTH.json +1739 -0
- package/swagger/dev/AUTHN.json +1250 -0
- package/swagger/dev/AUTHZ.json +1404 -0
- package/swagger/dev/CM.json +309 -0
- package/swagger/dev/COMMON.json +6543 -0
- package/swagger/dev/ES.json +28029 -0
- package/swagger/dev/EXPORT.json +4575 -0
- package/swagger/dev/IMPORT.json +1479 -0
- package/swagger/dev/LIC.json +224 -0
- package/swagger/dev/MSG.json +7883 -0
- package/swagger/dev/NEWS.json +348 -0
- package/swagger/dev/PA.json +5981 -0
- package/swagger/dev/PMP.json +3196 -0
- package/swagger/dev/PROXY.json +416 -0
- package/swagger/dev/REPORT.json +3921 -0
- package/swagger/dev/SC.json +3771 -0
- package/swagger/dev/SLA.json +2837 -0
- package/swagger/dev/TSTG.json +4981 -0
- package/swagger/dev/UI.json +4720 -0
- package/swagger/dev/WH.json +16796 -0
- package/swagger/dev/WORK.json +36024 -0
- package/swagger/dev/WSP.json +1612 -0
- package/swagger/prod/ADM.json +27777 -0
- package/swagger/prod/AUTH.json +1308 -0
- package/swagger/prod/AUTHN.json +2710 -0
- package/swagger/prod/AUTHZ.json +896 -0
- package/swagger/prod/CM.json +162 -0
- package/swagger/prod/COMMON.json +4910 -0
- package/swagger/prod/ES.json +28029 -0
- package/swagger/prod/EXPORT.json +3091 -0
- package/swagger/prod/LIC.json +123 -0
- package/swagger/prod/MSG.json +6239 -0
- package/swagger/prod/NEWS.json +295 -0
- package/swagger/prod/PA.json +5123 -0
- package/swagger/prod/PMP.json +2978 -0
- package/swagger/prod/PROXY.json +250 -0
- package/swagger/prod/REPORT.json +3729 -0
- package/swagger/prod/SC.json +3771 -0
- package/swagger/prod/SLA.json +2201 -0
- package/swagger/prod/TSTG.json +4220 -0
- package/swagger/prod/UI.json +3879 -0
- package/swagger/prod/WH.json +16730 -0
- package/swagger/prod/WORK.json +35994 -0
- package/swagger/prod/WSP.json +1468 -0
|
@@ -0,0 +1,1404 @@
|
|
|
1
|
+
{
|
|
2
|
+
"openapi": "3.0.1",
|
|
3
|
+
"info": {
|
|
4
|
+
"title": "API авторизации HubEx",
|
|
5
|
+
"description": "Выполняет авторизацию учётной записи в тенанте, выпуск и обновление JWT, управление refresh- и service-токенами.",
|
|
6
|
+
"contact": {
|
|
7
|
+
"name": "SmartService Backend Team",
|
|
8
|
+
"email": "fmbackend@melston.ru"
|
|
9
|
+
},
|
|
10
|
+
"version": "v1.0.0.0"
|
|
11
|
+
},
|
|
12
|
+
"servers": [
|
|
13
|
+
{
|
|
14
|
+
"url": "/AUTHZ"
|
|
15
|
+
}
|
|
16
|
+
],
|
|
17
|
+
"paths": {
|
|
18
|
+
"/AccessTokens": {
|
|
19
|
+
"post": {
|
|
20
|
+
"tags": [
|
|
21
|
+
"AccessTokens"
|
|
22
|
+
],
|
|
23
|
+
"summary": "Обновляет access-токен по refresh-токену, одноразовому токену или сервисному токену.",
|
|
24
|
+
"description": "Поддерживает три способа аутентификации (достаточно одного):\r\n- `refreshJwt` — JWT refresh-токен;\r\n- `oneTimeLoginToken` + `tenantID` — одноразовый токен входа;\r\n- `serviceToken` — сервисный токен.\r\n \r\nПри заголовке `X-Use-Cookie: true` refresh-токен читается из cookie `RefreshTokenCookie`; в теле достаточно пустого JSON-объекта `{}` (поле `refreshJwt` необязательно). Отсутствие тела запроса не поддерживается.\r\n \r\nОпциональный заголовок `X-Application-ID` проверяет доступ к указанному приложению.\r\n \r\n## Пример запроса (refresh-токен):\r\n```json\r\nPOST /AccessTokens\r\n \r\n{\r\n \"refreshJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"accessJwt\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\"\r\n}\r\n```\r\n \r\n## Пример запроса (X-Use-Cookie):\r\n```json\r\nPOST /AccessTokens\r\nX-Use-Cookie: true\r\n \r\n{}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": { \"userID\": 42, \"firstName\": \"Иван\", \"lastName\": \"Иванов\" },\r\n \"permissions\": {},\r\n \"tenant\": { \"id\": 10, \"name\": \"Demo\", \"fullName\": \"Demo Tenant LLC\", \"uriName\": \"demo\" },\r\n \"tenantMember\": { \"id\": 1001, \"userID\": 42, \"accountID\": 100 }\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — не удалось определить члена тенанта по переданным данным.\r\n- 400 Bad Request — отсутствует тело при работе без cookie, некорректный или просроченный токен.\r\n- 403 Forbidden — нет доступа к указанному приложению (заголовок `X-Application-ID`).",
|
|
25
|
+
"parameters": [
|
|
26
|
+
{
|
|
27
|
+
"name": "X-Application-ID",
|
|
28
|
+
"in": "header",
|
|
29
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
30
|
+
"schema": {
|
|
31
|
+
"enum": [
|
|
32
|
+
1,
|
|
33
|
+
2,
|
|
34
|
+
3,
|
|
35
|
+
4,
|
|
36
|
+
5,
|
|
37
|
+
6
|
|
38
|
+
],
|
|
39
|
+
"type": "integer",
|
|
40
|
+
"format": "int32",
|
|
41
|
+
"default": 3,
|
|
42
|
+
"x-enumNames": [
|
|
43
|
+
"EngineerMobile",
|
|
44
|
+
"CustomerMobile",
|
|
45
|
+
"MainWeb",
|
|
46
|
+
"AdminWeb",
|
|
47
|
+
"Api",
|
|
48
|
+
"PlateWeb"
|
|
49
|
+
]
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
],
|
|
53
|
+
"requestBody": {
|
|
54
|
+
"description": "Данные для обновления access-токена.",
|
|
55
|
+
"content": {
|
|
56
|
+
"application/json-patch+json": {
|
|
57
|
+
"schema": {
|
|
58
|
+
"$ref": "#/components/schemas/RefreshData"
|
|
59
|
+
}
|
|
60
|
+
},
|
|
61
|
+
"application/json": {
|
|
62
|
+
"schema": {
|
|
63
|
+
"$ref": "#/components/schemas/RefreshData"
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"text/json": {
|
|
67
|
+
"schema": {
|
|
68
|
+
"$ref": "#/components/schemas/RefreshData"
|
|
69
|
+
}
|
|
70
|
+
},
|
|
71
|
+
"application/*+json": {
|
|
72
|
+
"schema": {
|
|
73
|
+
"$ref": "#/components/schemas/RefreshData"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"responses": {
|
|
79
|
+
"200": {
|
|
80
|
+
"description": "Access-токен успешно обновлён.",
|
|
81
|
+
"content": {
|
|
82
|
+
"text/plain": {
|
|
83
|
+
"schema": {
|
|
84
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
"application/json": {
|
|
88
|
+
"schema": {
|
|
89
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
"text/json": {
|
|
93
|
+
"schema": {
|
|
94
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
},
|
|
99
|
+
"400": {
|
|
100
|
+
"description": "Некорректные данные или токен.",
|
|
101
|
+
"content": {
|
|
102
|
+
"text/plain": {
|
|
103
|
+
"schema": {
|
|
104
|
+
"type": "array",
|
|
105
|
+
"items": {
|
|
106
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
},
|
|
110
|
+
"application/json": {
|
|
111
|
+
"schema": {
|
|
112
|
+
"type": "array",
|
|
113
|
+
"items": {
|
|
114
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
},
|
|
118
|
+
"text/json": {
|
|
119
|
+
"schema": {
|
|
120
|
+
"type": "array",
|
|
121
|
+
"items": {
|
|
122
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
},
|
|
128
|
+
"401": {
|
|
129
|
+
"description": "Член тенанта не найден."
|
|
130
|
+
},
|
|
131
|
+
"403": {
|
|
132
|
+
"description": "Нет доступа к приложению.",
|
|
133
|
+
"content": {
|
|
134
|
+
"text/plain": {
|
|
135
|
+
"schema": {
|
|
136
|
+
"type": "array",
|
|
137
|
+
"items": {
|
|
138
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
},
|
|
142
|
+
"application/json": {
|
|
143
|
+
"schema": {
|
|
144
|
+
"type": "array",
|
|
145
|
+
"items": {
|
|
146
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
"text/json": {
|
|
151
|
+
"schema": {
|
|
152
|
+
"type": "array",
|
|
153
|
+
"items": {
|
|
154
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
"/Accounts/authorize": {
|
|
164
|
+
"post": {
|
|
165
|
+
"tags": [
|
|
166
|
+
"Accounts"
|
|
167
|
+
],
|
|
168
|
+
"summary": "Авторизует учётную запись в указанном тенанте.",
|
|
169
|
+
"description": "Тело запроса целиком можно опустить — тогда `tenantID` и `tenantMemberID` берутся из JWT текущего пользователя.\r\nЕсли тело передано, оба поля (`tenantID`, `tenantMemberID`) обязательны и должны быть больше 0.\r\n \r\n## Пример запроса:\r\n```json\r\nPOST /Accounts/authorize\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"tenantID\": 10,\r\n \"tenantMemberID\": 1001\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\",\r\n \"profile\": {\r\n \"userID\": 42,\r\n \"firstName\": \"Иван\",\r\n \"lastName\": \"Иванов\"\r\n },\r\n \"permissions\": { \"TaskView\": \"Allow\" },\r\n \"tenantLicenses\": [],\r\n \"featureFlags\": [],\r\n \"roleTaskAttribute\": []\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — передано неполное или некорректное тело (например `{}` или только одно из полей).",
|
|
170
|
+
"parameters": [
|
|
171
|
+
{
|
|
172
|
+
"name": "X-Application-ID",
|
|
173
|
+
"in": "header",
|
|
174
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
175
|
+
"schema": {
|
|
176
|
+
"enum": [
|
|
177
|
+
1,
|
|
178
|
+
2,
|
|
179
|
+
3,
|
|
180
|
+
4,
|
|
181
|
+
5,
|
|
182
|
+
6
|
|
183
|
+
],
|
|
184
|
+
"type": "integer",
|
|
185
|
+
"format": "int32",
|
|
186
|
+
"default": 3,
|
|
187
|
+
"x-enumNames": [
|
|
188
|
+
"EngineerMobile",
|
|
189
|
+
"CustomerMobile",
|
|
190
|
+
"MainWeb",
|
|
191
|
+
"AdminWeb",
|
|
192
|
+
"Api",
|
|
193
|
+
"PlateWeb"
|
|
194
|
+
]
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
],
|
|
198
|
+
"requestBody": {
|
|
199
|
+
"description": "Данные для авторизации в тенанте. Не передавайте тело, чтобы использовать значения из JWT.",
|
|
200
|
+
"content": {
|
|
201
|
+
"application/json-patch+json": {
|
|
202
|
+
"schema": {
|
|
203
|
+
"$ref": "#/components/schemas/AuthorizeData"
|
|
204
|
+
}
|
|
205
|
+
},
|
|
206
|
+
"application/json": {
|
|
207
|
+
"schema": {
|
|
208
|
+
"$ref": "#/components/schemas/AuthorizeData"
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
"text/json": {
|
|
212
|
+
"schema": {
|
|
213
|
+
"$ref": "#/components/schemas/AuthorizeData"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
"application/*+json": {
|
|
217
|
+
"schema": {
|
|
218
|
+
"$ref": "#/components/schemas/AuthorizeData"
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
"responses": {
|
|
224
|
+
"200": {
|
|
225
|
+
"description": "Авторизация в тенанте выполнена успешно.",
|
|
226
|
+
"content": {
|
|
227
|
+
"text/plain": {
|
|
228
|
+
"schema": {
|
|
229
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
230
|
+
}
|
|
231
|
+
},
|
|
232
|
+
"application/json": {
|
|
233
|
+
"schema": {
|
|
234
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"text/json": {
|
|
238
|
+
"schema": {
|
|
239
|
+
"$ref": "#/components/schemas/TenantMemberAuthorizationResult"
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
},
|
|
244
|
+
"400": {
|
|
245
|
+
"description": "Некорректные данные запроса.",
|
|
246
|
+
"content": {
|
|
247
|
+
"text/plain": {
|
|
248
|
+
"schema": {
|
|
249
|
+
"type": "array",
|
|
250
|
+
"items": {
|
|
251
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
},
|
|
255
|
+
"application/json": {
|
|
256
|
+
"schema": {
|
|
257
|
+
"type": "array",
|
|
258
|
+
"items": {
|
|
259
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
},
|
|
263
|
+
"text/json": {
|
|
264
|
+
"schema": {
|
|
265
|
+
"type": "array",
|
|
266
|
+
"items": {
|
|
267
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
},
|
|
273
|
+
"401": {
|
|
274
|
+
"description": "Токен отсутствует или некорректен."
|
|
275
|
+
},
|
|
276
|
+
"403": {
|
|
277
|
+
"description": "Forbidden"
|
|
278
|
+
}
|
|
279
|
+
},
|
|
280
|
+
"security": [
|
|
281
|
+
{
|
|
282
|
+
"Bearer": [ ]
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
},
|
|
287
|
+
"/RefreshTokens": {
|
|
288
|
+
"post": {
|
|
289
|
+
"tags": [
|
|
290
|
+
"RefreshTokens"
|
|
291
|
+
],
|
|
292
|
+
"summary": "Генерирует refresh-токен для текущего члена тенанта.",
|
|
293
|
+
"description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример запроса:\r\n```json\r\nPOST /RefreshTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n{\r\n \"validity\": \"30.00:00:00\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (200/201):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200/201):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — некорректные параметры или ошибка настройки CORS при использовании cookie.",
|
|
294
|
+
"parameters": [
|
|
295
|
+
{
|
|
296
|
+
"name": "X-Application-ID",
|
|
297
|
+
"in": "header",
|
|
298
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
299
|
+
"schema": {
|
|
300
|
+
"enum": [
|
|
301
|
+
1,
|
|
302
|
+
2,
|
|
303
|
+
3,
|
|
304
|
+
4,
|
|
305
|
+
5,
|
|
306
|
+
6
|
|
307
|
+
],
|
|
308
|
+
"type": "integer",
|
|
309
|
+
"format": "int32",
|
|
310
|
+
"default": 3,
|
|
311
|
+
"x-enumNames": [
|
|
312
|
+
"EngineerMobile",
|
|
313
|
+
"CustomerMobile",
|
|
314
|
+
"MainWeb",
|
|
315
|
+
"AdminWeb",
|
|
316
|
+
"Api",
|
|
317
|
+
"PlateWeb"
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
],
|
|
322
|
+
"requestBody": {
|
|
323
|
+
"description": "Параметры генерации (опционально).",
|
|
324
|
+
"content": {
|
|
325
|
+
"application/json-patch+json": {
|
|
326
|
+
"schema": {
|
|
327
|
+
"$ref": "#/components/schemas/GenerateData"
|
|
328
|
+
}
|
|
329
|
+
},
|
|
330
|
+
"application/json": {
|
|
331
|
+
"schema": {
|
|
332
|
+
"$ref": "#/components/schemas/GenerateData"
|
|
333
|
+
}
|
|
334
|
+
},
|
|
335
|
+
"text/json": {
|
|
336
|
+
"schema": {
|
|
337
|
+
"$ref": "#/components/schemas/GenerateData"
|
|
338
|
+
}
|
|
339
|
+
},
|
|
340
|
+
"application/*+json": {
|
|
341
|
+
"schema": {
|
|
342
|
+
"$ref": "#/components/schemas/GenerateData"
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
},
|
|
347
|
+
"responses": {
|
|
348
|
+
"200": {
|
|
349
|
+
"description": "Refresh-токен успешно получен (существующий).",
|
|
350
|
+
"content": {
|
|
351
|
+
"text/plain": {
|
|
352
|
+
"schema": {
|
|
353
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
354
|
+
}
|
|
355
|
+
},
|
|
356
|
+
"application/json": {
|
|
357
|
+
"schema": {
|
|
358
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
359
|
+
}
|
|
360
|
+
},
|
|
361
|
+
"text/json": {
|
|
362
|
+
"schema": {
|
|
363
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
},
|
|
368
|
+
"201": {
|
|
369
|
+
"description": "Refresh-токен успешно создан.",
|
|
370
|
+
"content": {
|
|
371
|
+
"text/plain": {
|
|
372
|
+
"schema": {
|
|
373
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
"application/json": {
|
|
377
|
+
"schema": {
|
|
378
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
"text/json": {
|
|
382
|
+
"schema": {
|
|
383
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
"400": {
|
|
389
|
+
"description": "Некорректные данные запроса.",
|
|
390
|
+
"content": {
|
|
391
|
+
"text/plain": {
|
|
392
|
+
"schema": {
|
|
393
|
+
"type": "array",
|
|
394
|
+
"items": {
|
|
395
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
"application/json": {
|
|
400
|
+
"schema": {
|
|
401
|
+
"type": "array",
|
|
402
|
+
"items": {
|
|
403
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
"text/json": {
|
|
408
|
+
"schema": {
|
|
409
|
+
"type": "array",
|
|
410
|
+
"items": {
|
|
411
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
},
|
|
417
|
+
"401": {
|
|
418
|
+
"description": "Токен отсутствует или некорректен."
|
|
419
|
+
},
|
|
420
|
+
"403": {
|
|
421
|
+
"description": "Forbidden"
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
"security": [
|
|
425
|
+
{
|
|
426
|
+
"Bearer": [ ]
|
|
427
|
+
}
|
|
428
|
+
]
|
|
429
|
+
},
|
|
430
|
+
"get": {
|
|
431
|
+
"tags": [
|
|
432
|
+
"RefreshTokens"
|
|
433
|
+
],
|
|
434
|
+
"summary": "Возвращает refresh-токен с параметрами по умолчанию.",
|
|
435
|
+
"description": "При заголовке `X-Use-Cookie: true` refresh-токен записывается в HttpOnly-cookie, тело ответа пустое.\r\n \r\n## Пример запроса:\r\n```text\r\nGET /RefreshTokens\r\nAuthorization: Bearer <access-token>\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"\",\r\n \"refresh_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 2592000,\r\n \"jwtValidTill\": \"2024-07-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nRefresh-токен не найден.\r\n \r\n## Пример успешного ответа при X-Use-Cookie (200):\r\nТело ответа пустое, refresh-токен в cookie `RefreshTokenCookie`.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — ошибка настройки CORS при использовании cookie.",
|
|
436
|
+
"parameters": [
|
|
437
|
+
{
|
|
438
|
+
"name": "X-Application-ID",
|
|
439
|
+
"in": "header",
|
|
440
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
441
|
+
"schema": {
|
|
442
|
+
"enum": [
|
|
443
|
+
1,
|
|
444
|
+
2,
|
|
445
|
+
3,
|
|
446
|
+
4,
|
|
447
|
+
5,
|
|
448
|
+
6
|
|
449
|
+
],
|
|
450
|
+
"type": "integer",
|
|
451
|
+
"format": "int32",
|
|
452
|
+
"default": 3,
|
|
453
|
+
"x-enumNames": [
|
|
454
|
+
"EngineerMobile",
|
|
455
|
+
"CustomerMobile",
|
|
456
|
+
"MainWeb",
|
|
457
|
+
"AdminWeb",
|
|
458
|
+
"Api",
|
|
459
|
+
"PlateWeb"
|
|
460
|
+
]
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
],
|
|
464
|
+
"responses": {
|
|
465
|
+
"200": {
|
|
466
|
+
"description": "Refresh-токен успешно получен.",
|
|
467
|
+
"content": {
|
|
468
|
+
"text/plain": {
|
|
469
|
+
"schema": {
|
|
470
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
471
|
+
}
|
|
472
|
+
},
|
|
473
|
+
"application/json": {
|
|
474
|
+
"schema": {
|
|
475
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
476
|
+
}
|
|
477
|
+
},
|
|
478
|
+
"text/json": {
|
|
479
|
+
"schema": {
|
|
480
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
}
|
|
484
|
+
},
|
|
485
|
+
"204": {
|
|
486
|
+
"description": "Refresh-токен не найден."
|
|
487
|
+
},
|
|
488
|
+
"400": {
|
|
489
|
+
"description": "Некорректные параметры запроса.",
|
|
490
|
+
"content": {
|
|
491
|
+
"text/plain": {
|
|
492
|
+
"schema": {
|
|
493
|
+
"type": "array",
|
|
494
|
+
"items": {
|
|
495
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
},
|
|
499
|
+
"application/json": {
|
|
500
|
+
"schema": {
|
|
501
|
+
"type": "array",
|
|
502
|
+
"items": {
|
|
503
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
},
|
|
507
|
+
"text/json": {
|
|
508
|
+
"schema": {
|
|
509
|
+
"type": "array",
|
|
510
|
+
"items": {
|
|
511
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
},
|
|
517
|
+
"401": {
|
|
518
|
+
"description": "Токен отсутствует или некорректен."
|
|
519
|
+
},
|
|
520
|
+
"403": {
|
|
521
|
+
"description": "Forbidden"
|
|
522
|
+
}
|
|
523
|
+
},
|
|
524
|
+
"security": [
|
|
525
|
+
{
|
|
526
|
+
"Bearer": [ ]
|
|
527
|
+
}
|
|
528
|
+
]
|
|
529
|
+
}
|
|
530
|
+
},
|
|
531
|
+
"/ServiceTokens": {
|
|
532
|
+
"post": {
|
|
533
|
+
"tags": [
|
|
534
|
+
"ServiceTokens"
|
|
535
|
+
],
|
|
536
|
+
"summary": "Генерирует сервисные токены для указанных членов тенанта.",
|
|
537
|
+
"description": "## Пример запроса:\r\n```json\r\nPOST /ServiceTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (201):\r\n```json\r\n[\r\n {\r\n \"token\": \"svc_abc123def456\",\r\n \"created\": \"2024-06-15T09:00:00Z\",\r\n \"validTill\": \"2025-06-15T09:00:00Z\"\r\n }\r\n]\r\n```\r\n \r\n## Пример успешного ответа (204):\r\nТело ответа пустое — новые токены не были созданы.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenAdd`).",
|
|
538
|
+
"parameters": [
|
|
539
|
+
{
|
|
540
|
+
"name": "X-Application-ID",
|
|
541
|
+
"in": "header",
|
|
542
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
543
|
+
"schema": {
|
|
544
|
+
"enum": [
|
|
545
|
+
1,
|
|
546
|
+
2,
|
|
547
|
+
3,
|
|
548
|
+
4,
|
|
549
|
+
5,
|
|
550
|
+
6
|
|
551
|
+
],
|
|
552
|
+
"type": "integer",
|
|
553
|
+
"format": "int32",
|
|
554
|
+
"default": 3,
|
|
555
|
+
"x-enumNames": [
|
|
556
|
+
"EngineerMobile",
|
|
557
|
+
"CustomerMobile",
|
|
558
|
+
"MainWeb",
|
|
559
|
+
"AdminWeb",
|
|
560
|
+
"Api",
|
|
561
|
+
"PlateWeb"
|
|
562
|
+
]
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
],
|
|
566
|
+
"requestBody": {
|
|
567
|
+
"description": "Список идентификаторов членов тенанта.",
|
|
568
|
+
"content": {
|
|
569
|
+
"application/json-patch+json": {
|
|
570
|
+
"schema": {
|
|
571
|
+
"type": "array",
|
|
572
|
+
"items": {
|
|
573
|
+
"type": "integer",
|
|
574
|
+
"format": "int32"
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
"application/json": {
|
|
579
|
+
"schema": {
|
|
580
|
+
"type": "array",
|
|
581
|
+
"items": {
|
|
582
|
+
"type": "integer",
|
|
583
|
+
"format": "int32"
|
|
584
|
+
}
|
|
585
|
+
}
|
|
586
|
+
},
|
|
587
|
+
"text/json": {
|
|
588
|
+
"schema": {
|
|
589
|
+
"type": "array",
|
|
590
|
+
"items": {
|
|
591
|
+
"type": "integer",
|
|
592
|
+
"format": "int32"
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
},
|
|
596
|
+
"application/*+json": {
|
|
597
|
+
"schema": {
|
|
598
|
+
"type": "array",
|
|
599
|
+
"items": {
|
|
600
|
+
"type": "integer",
|
|
601
|
+
"format": "int32"
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
},
|
|
607
|
+
"responses": {
|
|
608
|
+
"201": {
|
|
609
|
+
"description": "Токены успешно созданы.",
|
|
610
|
+
"content": {
|
|
611
|
+
"text/plain": {
|
|
612
|
+
"schema": {
|
|
613
|
+
"type": "array",
|
|
614
|
+
"items": {
|
|
615
|
+
"$ref": "#/components/schemas/PostResult"
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
},
|
|
619
|
+
"application/json": {
|
|
620
|
+
"schema": {
|
|
621
|
+
"type": "array",
|
|
622
|
+
"items": {
|
|
623
|
+
"$ref": "#/components/schemas/PostResult"
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
},
|
|
627
|
+
"text/json": {
|
|
628
|
+
"schema": {
|
|
629
|
+
"type": "array",
|
|
630
|
+
"items": {
|
|
631
|
+
"$ref": "#/components/schemas/PostResult"
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
},
|
|
637
|
+
"204": {
|
|
638
|
+
"description": "Новые токены не созданы."
|
|
639
|
+
},
|
|
640
|
+
"401": {
|
|
641
|
+
"description": "Токен отсутствует или некорректен."
|
|
642
|
+
},
|
|
643
|
+
"403": {
|
|
644
|
+
"description": "Недостаточно прав.",
|
|
645
|
+
"content": {
|
|
646
|
+
"text/plain": {
|
|
647
|
+
"schema": {
|
|
648
|
+
"type": "array",
|
|
649
|
+
"items": {
|
|
650
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
},
|
|
654
|
+
"application/json": {
|
|
655
|
+
"schema": {
|
|
656
|
+
"type": "array",
|
|
657
|
+
"items": {
|
|
658
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
},
|
|
662
|
+
"text/json": {
|
|
663
|
+
"schema": {
|
|
664
|
+
"type": "array",
|
|
665
|
+
"items": {
|
|
666
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
667
|
+
}
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
},
|
|
673
|
+
"security": [
|
|
674
|
+
{
|
|
675
|
+
"Bearer": [ ]
|
|
676
|
+
}
|
|
677
|
+
]
|
|
678
|
+
},
|
|
679
|
+
"delete": {
|
|
680
|
+
"tags": [
|
|
681
|
+
"ServiceTokens"
|
|
682
|
+
],
|
|
683
|
+
"summary": "Удаляет сервисные токены указанных членов тенанта.",
|
|
684
|
+
"description": "## Пример запроса:\r\n```json\r\nDELETE /ServiceTokens\r\nAuthorization: Bearer <access-token>\r\n \r\n[1001, 1002]\r\n```\r\n \r\n## Пример успешного ответа (202):\r\nТело ответа пустое.\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 403 Forbidden — недостаточно прав (`ServiceTokenRemove`).",
|
|
685
|
+
"parameters": [
|
|
686
|
+
{
|
|
687
|
+
"name": "X-Application-ID",
|
|
688
|
+
"in": "header",
|
|
689
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
690
|
+
"schema": {
|
|
691
|
+
"enum": [
|
|
692
|
+
1,
|
|
693
|
+
2,
|
|
694
|
+
3,
|
|
695
|
+
4,
|
|
696
|
+
5,
|
|
697
|
+
6
|
|
698
|
+
],
|
|
699
|
+
"type": "integer",
|
|
700
|
+
"format": "int32",
|
|
701
|
+
"default": 3,
|
|
702
|
+
"x-enumNames": [
|
|
703
|
+
"EngineerMobile",
|
|
704
|
+
"CustomerMobile",
|
|
705
|
+
"MainWeb",
|
|
706
|
+
"AdminWeb",
|
|
707
|
+
"Api",
|
|
708
|
+
"PlateWeb"
|
|
709
|
+
]
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
],
|
|
713
|
+
"requestBody": {
|
|
714
|
+
"description": "Список идентификаторов членов тенанта.",
|
|
715
|
+
"content": {
|
|
716
|
+
"application/json-patch+json": {
|
|
717
|
+
"schema": {
|
|
718
|
+
"type": "array",
|
|
719
|
+
"items": {
|
|
720
|
+
"type": "integer",
|
|
721
|
+
"format": "int32"
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
},
|
|
725
|
+
"application/json": {
|
|
726
|
+
"schema": {
|
|
727
|
+
"type": "array",
|
|
728
|
+
"items": {
|
|
729
|
+
"type": "integer",
|
|
730
|
+
"format": "int32"
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
},
|
|
734
|
+
"text/json": {
|
|
735
|
+
"schema": {
|
|
736
|
+
"type": "array",
|
|
737
|
+
"items": {
|
|
738
|
+
"type": "integer",
|
|
739
|
+
"format": "int32"
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
},
|
|
743
|
+
"application/*+json": {
|
|
744
|
+
"schema": {
|
|
745
|
+
"type": "array",
|
|
746
|
+
"items": {
|
|
747
|
+
"type": "integer",
|
|
748
|
+
"format": "int32"
|
|
749
|
+
}
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
},
|
|
754
|
+
"responses": {
|
|
755
|
+
"202": {
|
|
756
|
+
"description": "Токены успешно удалены."
|
|
757
|
+
},
|
|
758
|
+
"401": {
|
|
759
|
+
"description": "Токен отсутствует или некорректен."
|
|
760
|
+
},
|
|
761
|
+
"403": {
|
|
762
|
+
"description": "Недостаточно прав.",
|
|
763
|
+
"content": {
|
|
764
|
+
"text/plain": {
|
|
765
|
+
"schema": {
|
|
766
|
+
"type": "array",
|
|
767
|
+
"items": {
|
|
768
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
},
|
|
772
|
+
"application/json": {
|
|
773
|
+
"schema": {
|
|
774
|
+
"type": "array",
|
|
775
|
+
"items": {
|
|
776
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
},
|
|
780
|
+
"text/json": {
|
|
781
|
+
"schema": {
|
|
782
|
+
"type": "array",
|
|
783
|
+
"items": {
|
|
784
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
785
|
+
}
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
},
|
|
791
|
+
"security": [
|
|
792
|
+
{
|
|
793
|
+
"Bearer": [ ]
|
|
794
|
+
}
|
|
795
|
+
]
|
|
796
|
+
}
|
|
797
|
+
},
|
|
798
|
+
"/Tokens/renew": {
|
|
799
|
+
"post": {
|
|
800
|
+
"tags": [
|
|
801
|
+
"Tokens"
|
|
802
|
+
],
|
|
803
|
+
"summary": "Продлевает срок действия текущего JWT access-токена.",
|
|
804
|
+
"description": "Токен извлекается из сохранённого Bearer-токена текущего запроса.\r\n \r\n## Пример запроса:\r\n```text\r\nPOST /Tokens/renew\r\nAuthorization: Bearer <access-token>\r\n```\r\n \r\n## Пример успешного ответа (200):\r\n```json\r\n{\r\n \"access_token\": \"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...\",\r\n \"expires_in\": 3600,\r\n \"jwtValidTill\": \"2024-06-15T10:00:00Z\"\r\n}\r\n```\r\n \r\n## Негативные сценарии:\r\n- 401 Unauthorized — отсутствует или некорректен Bearer-токен.\r\n- 400 Bad Request — access-токен не найден в контексте аутентификации.",
|
|
805
|
+
"parameters": [
|
|
806
|
+
{
|
|
807
|
+
"name": "X-Application-ID",
|
|
808
|
+
"in": "header",
|
|
809
|
+
"description": "Идентификатор приложения. EngineerMobile - 1, CustomerMobile - 2, MainWeb - 3, AdminWeb - 4, Api - 5, PlateWeb - 6",
|
|
810
|
+
"schema": {
|
|
811
|
+
"enum": [
|
|
812
|
+
1,
|
|
813
|
+
2,
|
|
814
|
+
3,
|
|
815
|
+
4,
|
|
816
|
+
5,
|
|
817
|
+
6
|
|
818
|
+
],
|
|
819
|
+
"type": "integer",
|
|
820
|
+
"format": "int32",
|
|
821
|
+
"default": 3,
|
|
822
|
+
"x-enumNames": [
|
|
823
|
+
"EngineerMobile",
|
|
824
|
+
"CustomerMobile",
|
|
825
|
+
"MainWeb",
|
|
826
|
+
"AdminWeb",
|
|
827
|
+
"Api",
|
|
828
|
+
"PlateWeb"
|
|
829
|
+
]
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
],
|
|
833
|
+
"responses": {
|
|
834
|
+
"200": {
|
|
835
|
+
"description": "Токен успешно обновлён.",
|
|
836
|
+
"content": {
|
|
837
|
+
"text/plain": {
|
|
838
|
+
"schema": {
|
|
839
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
840
|
+
}
|
|
841
|
+
},
|
|
842
|
+
"application/json": {
|
|
843
|
+
"schema": {
|
|
844
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
845
|
+
}
|
|
846
|
+
},
|
|
847
|
+
"text/json": {
|
|
848
|
+
"schema": {
|
|
849
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
},
|
|
854
|
+
"400": {
|
|
855
|
+
"description": "Access-токен отсутствует.",
|
|
856
|
+
"content": {
|
|
857
|
+
"text/plain": {
|
|
858
|
+
"schema": {
|
|
859
|
+
"type": "array",
|
|
860
|
+
"items": {
|
|
861
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
},
|
|
865
|
+
"application/json": {
|
|
866
|
+
"schema": {
|
|
867
|
+
"type": "array",
|
|
868
|
+
"items": {
|
|
869
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
},
|
|
873
|
+
"text/json": {
|
|
874
|
+
"schema": {
|
|
875
|
+
"type": "array",
|
|
876
|
+
"items": {
|
|
877
|
+
"$ref": "#/components/schemas/ErrorModel"
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
},
|
|
883
|
+
"401": {
|
|
884
|
+
"description": "Токен отсутствует или некорректен."
|
|
885
|
+
},
|
|
886
|
+
"403": {
|
|
887
|
+
"description": "Forbidden"
|
|
888
|
+
}
|
|
889
|
+
},
|
|
890
|
+
"security": [
|
|
891
|
+
{
|
|
892
|
+
"Bearer": [ ]
|
|
893
|
+
}
|
|
894
|
+
]
|
|
895
|
+
}
|
|
896
|
+
}
|
|
897
|
+
},
|
|
898
|
+
"components": {
|
|
899
|
+
"schemas": {
|
|
900
|
+
"AuthorizeData": {
|
|
901
|
+
"required": [
|
|
902
|
+
"tenantID",
|
|
903
|
+
"tenantMemberID"
|
|
904
|
+
],
|
|
905
|
+
"type": "object",
|
|
906
|
+
"properties": {
|
|
907
|
+
"tenantID": {
|
|
908
|
+
"type": "integer",
|
|
909
|
+
"description": "ИД тенанта, в который будет авторизован пользователь.",
|
|
910
|
+
"format": "int32",
|
|
911
|
+
"example": 10
|
|
912
|
+
},
|
|
913
|
+
"tenantMemberID": {
|
|
914
|
+
"type": "integer",
|
|
915
|
+
"description": "ИД члена тенанта, в который этот член будет авторизован.",
|
|
916
|
+
"format": "int32",
|
|
917
|
+
"example": 1001
|
|
918
|
+
}
|
|
919
|
+
},
|
|
920
|
+
"additionalProperties": false,
|
|
921
|
+
"description": "Данные для авторизации в тенанте. Если тело запроса передаётся, оба поля обязательны."
|
|
922
|
+
},
|
|
923
|
+
"ErrorModel": {
|
|
924
|
+
"type": "object",
|
|
925
|
+
"properties": {
|
|
926
|
+
"traceIdentifier": {
|
|
927
|
+
"type": "string",
|
|
928
|
+
"nullable": true
|
|
929
|
+
},
|
|
930
|
+
"code": {
|
|
931
|
+
"type": "string",
|
|
932
|
+
"nullable": true
|
|
933
|
+
},
|
|
934
|
+
"message": {
|
|
935
|
+
"type": "string",
|
|
936
|
+
"nullable": true
|
|
937
|
+
},
|
|
938
|
+
"arguments": {
|
|
939
|
+
"type": "object",
|
|
940
|
+
"additionalProperties": {
|
|
941
|
+
"type": "string",
|
|
942
|
+
"nullable": true
|
|
943
|
+
},
|
|
944
|
+
"nullable": true
|
|
945
|
+
}
|
|
946
|
+
},
|
|
947
|
+
"additionalProperties": false
|
|
948
|
+
},
|
|
949
|
+
"GenerateData": {
|
|
950
|
+
"type": "object",
|
|
951
|
+
"properties": {
|
|
952
|
+
"validity": {
|
|
953
|
+
"type": "string",
|
|
954
|
+
"description": "Срок действия токена",
|
|
955
|
+
"format": "date-span",
|
|
956
|
+
"nullable": true,
|
|
957
|
+
"example": "30.00:00:00"
|
|
958
|
+
}
|
|
959
|
+
},
|
|
960
|
+
"additionalProperties": false,
|
|
961
|
+
"description": "Параметры генерации токена"
|
|
962
|
+
},
|
|
963
|
+
"IdCodeNameResultOfShort": {
|
|
964
|
+
"type": "object",
|
|
965
|
+
"properties": {
|
|
966
|
+
"id": {
|
|
967
|
+
"type": "integer",
|
|
968
|
+
"format": "int32"
|
|
969
|
+
},
|
|
970
|
+
"code": {
|
|
971
|
+
"type": "string",
|
|
972
|
+
"nullable": true
|
|
973
|
+
},
|
|
974
|
+
"name": {
|
|
975
|
+
"type": "string",
|
|
976
|
+
"nullable": true
|
|
977
|
+
}
|
|
978
|
+
},
|
|
979
|
+
"additionalProperties": false
|
|
980
|
+
},
|
|
981
|
+
"IdNameResultOfByte": {
|
|
982
|
+
"type": "object",
|
|
983
|
+
"properties": {
|
|
984
|
+
"id": {
|
|
985
|
+
"type": "integer",
|
|
986
|
+
"format": "int32"
|
|
987
|
+
},
|
|
988
|
+
"name": {
|
|
989
|
+
"type": "string",
|
|
990
|
+
"nullable": true
|
|
991
|
+
}
|
|
992
|
+
},
|
|
993
|
+
"additionalProperties": false
|
|
994
|
+
},
|
|
995
|
+
"JwtResultBase": {
|
|
996
|
+
"type": "object",
|
|
997
|
+
"properties": {
|
|
998
|
+
"access_token": {
|
|
999
|
+
"type": "string",
|
|
1000
|
+
"description": "JWT-токен для доступа к ресурсам",
|
|
1001
|
+
"nullable": true,
|
|
1002
|
+
"readOnly": true,
|
|
1003
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1004
|
+
},
|
|
1005
|
+
"refresh_token": {
|
|
1006
|
+
"type": "string",
|
|
1007
|
+
"description": "JWT-токен для обновления JWT-токена для доступа к ресурсам",
|
|
1008
|
+
"nullable": true,
|
|
1009
|
+
"readOnly": true,
|
|
1010
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1011
|
+
},
|
|
1012
|
+
"expires_in": {
|
|
1013
|
+
"type": "integer",
|
|
1014
|
+
"description": "Количество секунд, через которой токен будет просрочен",
|
|
1015
|
+
"format": "int32",
|
|
1016
|
+
"nullable": true,
|
|
1017
|
+
"readOnly": true,
|
|
1018
|
+
"example": 3600
|
|
1019
|
+
},
|
|
1020
|
+
"jwtValidTill": {
|
|
1021
|
+
"type": "string",
|
|
1022
|
+
"description": "Метка времени в UTC, до которой действует JWT",
|
|
1023
|
+
"format": "date-time",
|
|
1024
|
+
"nullable": true,
|
|
1025
|
+
"example": "2024-06-15T10:00:00Z"
|
|
1026
|
+
}
|
|
1027
|
+
},
|
|
1028
|
+
"additionalProperties": false,
|
|
1029
|
+
"description": "Данные JWT"
|
|
1030
|
+
},
|
|
1031
|
+
"PostResult": {
|
|
1032
|
+
"type": "object",
|
|
1033
|
+
"properties": {
|
|
1034
|
+
"token": {
|
|
1035
|
+
"type": "string",
|
|
1036
|
+
"description": "Токен",
|
|
1037
|
+
"nullable": true,
|
|
1038
|
+
"example": "svc_abc123def456"
|
|
1039
|
+
},
|
|
1040
|
+
"created": {
|
|
1041
|
+
"type": "string",
|
|
1042
|
+
"description": "Метка времени создания токена",
|
|
1043
|
+
"format": "date-time",
|
|
1044
|
+
"example": "2024-06-15T09:00:00Z"
|
|
1045
|
+
},
|
|
1046
|
+
"validTill": {
|
|
1047
|
+
"type": "string",
|
|
1048
|
+
"description": "Срок действия токена",
|
|
1049
|
+
"format": "date-time",
|
|
1050
|
+
"example": "2025-06-15T09:00:00Z"
|
|
1051
|
+
}
|
|
1052
|
+
},
|
|
1053
|
+
"additionalProperties": false,
|
|
1054
|
+
"description": "Результат генерации сервисного токена"
|
|
1055
|
+
},
|
|
1056
|
+
"RefreshData": {
|
|
1057
|
+
"type": "object",
|
|
1058
|
+
"properties": {
|
|
1059
|
+
"jwt": {
|
|
1060
|
+
"type": "string",
|
|
1061
|
+
"description": "JWT refresh-токен",
|
|
1062
|
+
"nullable": true,
|
|
1063
|
+
"deprecated": true
|
|
1064
|
+
},
|
|
1065
|
+
"refreshJwt": {
|
|
1066
|
+
"type": "string",
|
|
1067
|
+
"description": "JWT refresh-токен",
|
|
1068
|
+
"nullable": true,
|
|
1069
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1070
|
+
},
|
|
1071
|
+
"accessJwt": {
|
|
1072
|
+
"type": "string",
|
|
1073
|
+
"description": "JWT access-токен (опциональный, необходим для определения включены ли в access-токен какие-либо расщирения, если включены новый токен будет сгенерирован с учетогм их)",
|
|
1074
|
+
"nullable": true,
|
|
1075
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1076
|
+
},
|
|
1077
|
+
"oneTimeLoginToken": {
|
|
1078
|
+
"type": "string",
|
|
1079
|
+
"description": "Токен для одноразовой авторизации в тенанте",
|
|
1080
|
+
"nullable": true,
|
|
1081
|
+
"example": "one-time-token-value"
|
|
1082
|
+
},
|
|
1083
|
+
"tenantID": {
|
|
1084
|
+
"type": "integer",
|
|
1085
|
+
"description": "Идентификатор тенанта, в который будет произведен вход по HubEx.Service.AUTHZ.Api.Data.AccessToken.RefreshData.OneTimeLoginToken",
|
|
1086
|
+
"format": "int32",
|
|
1087
|
+
"nullable": true,
|
|
1088
|
+
"example": 10
|
|
1089
|
+
},
|
|
1090
|
+
"serviceToken": {
|
|
1091
|
+
"type": "string",
|
|
1092
|
+
"description": "Сервисный токен для упрощенной авторизации",
|
|
1093
|
+
"nullable": true,
|
|
1094
|
+
"example": "svc_abc123def456"
|
|
1095
|
+
}
|
|
1096
|
+
},
|
|
1097
|
+
"additionalProperties": false,
|
|
1098
|
+
"description": "Класс, принимающий JWT для обновления JWT доступа к ресурсам."
|
|
1099
|
+
},
|
|
1100
|
+
"TenantLicenseCurrentResult": {
|
|
1101
|
+
"type": "object",
|
|
1102
|
+
"properties": {
|
|
1103
|
+
"license": {
|
|
1104
|
+
"$ref": "#/components/schemas/IdCodeNameResultOfShort"
|
|
1105
|
+
},
|
|
1106
|
+
"dateTill": {
|
|
1107
|
+
"type": "string",
|
|
1108
|
+
"description": "Дата окончания лицензии",
|
|
1109
|
+
"format": "date-time",
|
|
1110
|
+
"example": "2025-12-31T23:59:59Z"
|
|
1111
|
+
},
|
|
1112
|
+
"isTrialPeriod": {
|
|
1113
|
+
"type": "boolean",
|
|
1114
|
+
"description": "Флаг пробного периода",
|
|
1115
|
+
"example": false
|
|
1116
|
+
},
|
|
1117
|
+
"dateFrom": {
|
|
1118
|
+
"type": "string",
|
|
1119
|
+
"description": "Дата начала лицензии",
|
|
1120
|
+
"format": "date-time",
|
|
1121
|
+
"example": "2024-01-01T00:00:00Z"
|
|
1122
|
+
},
|
|
1123
|
+
"trialPeriodDays": {
|
|
1124
|
+
"type": "integer",
|
|
1125
|
+
"description": "Длина пробного периода в днях",
|
|
1126
|
+
"format": "int32",
|
|
1127
|
+
"nullable": true,
|
|
1128
|
+
"example": 14
|
|
1129
|
+
}
|
|
1130
|
+
},
|
|
1131
|
+
"additionalProperties": false,
|
|
1132
|
+
"description": "Данные текущей лицензии тенанта"
|
|
1133
|
+
},
|
|
1134
|
+
"TenantMemberAuthorizationResult": {
|
|
1135
|
+
"type": "object",
|
|
1136
|
+
"properties": {
|
|
1137
|
+
"access_token": {
|
|
1138
|
+
"type": "string",
|
|
1139
|
+
"description": "JWT-токен для доступа к ресурсам",
|
|
1140
|
+
"nullable": true,
|
|
1141
|
+
"readOnly": true,
|
|
1142
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1143
|
+
},
|
|
1144
|
+
"refresh_token": {
|
|
1145
|
+
"type": "string",
|
|
1146
|
+
"description": "JWT-токен для обновления JWT-токена для доступа к ресурсам",
|
|
1147
|
+
"nullable": true,
|
|
1148
|
+
"readOnly": true,
|
|
1149
|
+
"example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..."
|
|
1150
|
+
},
|
|
1151
|
+
"expires_in": {
|
|
1152
|
+
"type": "integer",
|
|
1153
|
+
"description": "Количество секунд, через которой токен будет просрочен",
|
|
1154
|
+
"format": "int32",
|
|
1155
|
+
"nullable": true,
|
|
1156
|
+
"readOnly": true,
|
|
1157
|
+
"example": 3600
|
|
1158
|
+
},
|
|
1159
|
+
"jwtValidTill": {
|
|
1160
|
+
"type": "string",
|
|
1161
|
+
"description": "Метка времени в UTC, до которой действует JWT",
|
|
1162
|
+
"format": "date-time",
|
|
1163
|
+
"nullable": true,
|
|
1164
|
+
"example": "2024-06-15T10:00:00Z"
|
|
1165
|
+
},
|
|
1166
|
+
"profile": {
|
|
1167
|
+
"$ref": "#/components/schemas/UserProfileResult"
|
|
1168
|
+
},
|
|
1169
|
+
"permissions": {
|
|
1170
|
+
"type": "object",
|
|
1171
|
+
"additionalProperties": {
|
|
1172
|
+
"type": "string",
|
|
1173
|
+
"nullable": true
|
|
1174
|
+
},
|
|
1175
|
+
"description": "Данные пользователя как члена тенанта.",
|
|
1176
|
+
"nullable": true
|
|
1177
|
+
},
|
|
1178
|
+
"refreshToken": {
|
|
1179
|
+
"$ref": "#/components/schemas/JwtResultBase"
|
|
1180
|
+
},
|
|
1181
|
+
"tenant": {
|
|
1182
|
+
"$ref": "#/components/schemas/TenantResult"
|
|
1183
|
+
},
|
|
1184
|
+
"tenantMember": {
|
|
1185
|
+
"$ref": "#/components/schemas/TenantMemberResult"
|
|
1186
|
+
},
|
|
1187
|
+
"tenantLicenses": {
|
|
1188
|
+
"type": "array",
|
|
1189
|
+
"items": {
|
|
1190
|
+
"$ref": "#/components/schemas/TenantLicenseCurrentResult"
|
|
1191
|
+
},
|
|
1192
|
+
"description": "Данные лицензий тенанта",
|
|
1193
|
+
"nullable": true
|
|
1194
|
+
},
|
|
1195
|
+
"featureFlags": {
|
|
1196
|
+
"type": "array",
|
|
1197
|
+
"items": {
|
|
1198
|
+
"type": "string"
|
|
1199
|
+
},
|
|
1200
|
+
"description": "Список флагов нового функционала, доступных тенанту",
|
|
1201
|
+
"nullable": true
|
|
1202
|
+
},
|
|
1203
|
+
"roleTaskAttribute": {
|
|
1204
|
+
"type": "array",
|
|
1205
|
+
"items": {
|
|
1206
|
+
"type": "integer",
|
|
1207
|
+
"format": "int32"
|
|
1208
|
+
},
|
|
1209
|
+
"description": "Список доступных атрибутов для ролей пользователя по заявке",
|
|
1210
|
+
"nullable": true
|
|
1211
|
+
}
|
|
1212
|
+
},
|
|
1213
|
+
"additionalProperties": false,
|
|
1214
|
+
"description": "Авторизация члена тенанта"
|
|
1215
|
+
},
|
|
1216
|
+
"TenantMemberResult": {
|
|
1217
|
+
"type": "object",
|
|
1218
|
+
"properties": {
|
|
1219
|
+
"id": {
|
|
1220
|
+
"type": "integer",
|
|
1221
|
+
"description": "Идентификатор члена тенанта",
|
|
1222
|
+
"format": "int32",
|
|
1223
|
+
"example": 1001
|
|
1224
|
+
},
|
|
1225
|
+
"description": {
|
|
1226
|
+
"type": "string",
|
|
1227
|
+
"description": "Описание",
|
|
1228
|
+
"nullable": true,
|
|
1229
|
+
"example": "Инженер участка"
|
|
1230
|
+
},
|
|
1231
|
+
"userID": {
|
|
1232
|
+
"type": "integer",
|
|
1233
|
+
"description": "Идентификатор пользователя",
|
|
1234
|
+
"format": "int32",
|
|
1235
|
+
"example": 42
|
|
1236
|
+
},
|
|
1237
|
+
"accountID": {
|
|
1238
|
+
"type": "integer",
|
|
1239
|
+
"description": "Идентификатор учетной записи",
|
|
1240
|
+
"format": "int32",
|
|
1241
|
+
"example": 100
|
|
1242
|
+
}
|
|
1243
|
+
},
|
|
1244
|
+
"additionalProperties": false,
|
|
1245
|
+
"description": "Данные члена тенанта"
|
|
1246
|
+
},
|
|
1247
|
+
"TenantResult": {
|
|
1248
|
+
"type": "object",
|
|
1249
|
+
"properties": {
|
|
1250
|
+
"id": {
|
|
1251
|
+
"type": "integer",
|
|
1252
|
+
"description": "Идентификатор тенанта",
|
|
1253
|
+
"format": "int32",
|
|
1254
|
+
"example": 10
|
|
1255
|
+
},
|
|
1256
|
+
"name": {
|
|
1257
|
+
"type": "string",
|
|
1258
|
+
"description": "Краткое название тенанта",
|
|
1259
|
+
"nullable": true,
|
|
1260
|
+
"example": "Demo"
|
|
1261
|
+
},
|
|
1262
|
+
"fullName": {
|
|
1263
|
+
"type": "string",
|
|
1264
|
+
"description": "Полное название тенанта",
|
|
1265
|
+
"nullable": true,
|
|
1266
|
+
"example": "Demo Tenant LLC"
|
|
1267
|
+
},
|
|
1268
|
+
"uriName": {
|
|
1269
|
+
"type": "string",
|
|
1270
|
+
"description": "Uri-постфикс",
|
|
1271
|
+
"nullable": true,
|
|
1272
|
+
"example": "demo"
|
|
1273
|
+
}
|
|
1274
|
+
},
|
|
1275
|
+
"additionalProperties": false,
|
|
1276
|
+
"description": "Данные тенанта"
|
|
1277
|
+
},
|
|
1278
|
+
"UserProfileResult": {
|
|
1279
|
+
"type": "object",
|
|
1280
|
+
"properties": {
|
|
1281
|
+
"userID": {
|
|
1282
|
+
"type": "integer",
|
|
1283
|
+
"description": "Идентификатор пользователя",
|
|
1284
|
+
"format": "int32",
|
|
1285
|
+
"example": 42
|
|
1286
|
+
},
|
|
1287
|
+
"firstName": {
|
|
1288
|
+
"type": "string",
|
|
1289
|
+
"description": "Имя",
|
|
1290
|
+
"nullable": true,
|
|
1291
|
+
"example": "Иван"
|
|
1292
|
+
},
|
|
1293
|
+
"lastName": {
|
|
1294
|
+
"type": "string",
|
|
1295
|
+
"description": "Фамилия",
|
|
1296
|
+
"nullable": true,
|
|
1297
|
+
"example": "Иванов"
|
|
1298
|
+
},
|
|
1299
|
+
"middleName": {
|
|
1300
|
+
"type": "string",
|
|
1301
|
+
"description": "Отчество",
|
|
1302
|
+
"nullable": true
|
|
1303
|
+
},
|
|
1304
|
+
"email": {
|
|
1305
|
+
"type": "string",
|
|
1306
|
+
"description": "Адрес эл.почты",
|
|
1307
|
+
"nullable": true,
|
|
1308
|
+
"example": "ivan.ivanov@example.com"
|
|
1309
|
+
},
|
|
1310
|
+
"mobilePhone": {
|
|
1311
|
+
"type": "string",
|
|
1312
|
+
"description": "Мобильный телефон",
|
|
1313
|
+
"nullable": true
|
|
1314
|
+
},
|
|
1315
|
+
"workPhone": {
|
|
1316
|
+
"type": "string",
|
|
1317
|
+
"description": "Рабочий телефон",
|
|
1318
|
+
"nullable": true
|
|
1319
|
+
},
|
|
1320
|
+
"otherPhone": {
|
|
1321
|
+
"type": "string",
|
|
1322
|
+
"description": "Другой телефон",
|
|
1323
|
+
"nullable": true
|
|
1324
|
+
},
|
|
1325
|
+
"avatarUrl": {
|
|
1326
|
+
"type": "string",
|
|
1327
|
+
"description": "Ссылка на аватар пользователя",
|
|
1328
|
+
"nullable": true
|
|
1329
|
+
},
|
|
1330
|
+
"geoTrackingMode": {
|
|
1331
|
+
"$ref": "#/components/schemas/IdNameResultOfByte"
|
|
1332
|
+
},
|
|
1333
|
+
"accountDomainLogin": {
|
|
1334
|
+
"type": "string",
|
|
1335
|
+
"description": "Domain login аккаунта пользователя",
|
|
1336
|
+
"nullable": true
|
|
1337
|
+
},
|
|
1338
|
+
"defaultPageWeb": {
|
|
1339
|
+
"type": "string",
|
|
1340
|
+
"description": "Стартовая страница для WEB",
|
|
1341
|
+
"nullable": true
|
|
1342
|
+
},
|
|
1343
|
+
"defaultPageMobile": {
|
|
1344
|
+
"type": "string",
|
|
1345
|
+
"description": "Стартовая страница для МП инженера",
|
|
1346
|
+
"nullable": true
|
|
1347
|
+
}
|
|
1348
|
+
},
|
|
1349
|
+
"additionalProperties": false,
|
|
1350
|
+
"description": "Профиль пользователя"
|
|
1351
|
+
}
|
|
1352
|
+
},
|
|
1353
|
+
"securitySchemes": {
|
|
1354
|
+
"Bearer": {
|
|
1355
|
+
"type": "http",
|
|
1356
|
+
"description": "Введите токен для авторизации",
|
|
1357
|
+
"scheme": "Bearer",
|
|
1358
|
+
"bearerFormat": "JWT"
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
},
|
|
1362
|
+
"tags": [
|
|
1363
|
+
{
|
|
1364
|
+
"name": "AccessTokens",
|
|
1365
|
+
"description": "Контроллер для управления токенами доступа"
|
|
1366
|
+
},
|
|
1367
|
+
{
|
|
1368
|
+
"name": "Accounts",
|
|
1369
|
+
"description": "Контроллер для аутентификации и авторизации учетных записей"
|
|
1370
|
+
},
|
|
1371
|
+
{
|
|
1372
|
+
"name": "RefreshTokens",
|
|
1373
|
+
"description": "Контроллер для управления токенами обновления токена доступа"
|
|
1374
|
+
},
|
|
1375
|
+
{
|
|
1376
|
+
"name": "ServiceTokens",
|
|
1377
|
+
"description": "Контроллер для управления сервисными токенами"
|
|
1378
|
+
},
|
|
1379
|
+
{
|
|
1380
|
+
"name": "Tokens",
|
|
1381
|
+
"description": "Контроллер для работы с JWT"
|
|
1382
|
+
},
|
|
1383
|
+
{
|
|
1384
|
+
"name": "AccessTokens",
|
|
1385
|
+
"description": "Контроллер для управления токенами доступа"
|
|
1386
|
+
},
|
|
1387
|
+
{
|
|
1388
|
+
"name": "Accounts",
|
|
1389
|
+
"description": "Контроллер для аутентификации и авторизации учетных записей"
|
|
1390
|
+
},
|
|
1391
|
+
{
|
|
1392
|
+
"name": "RefreshTokens",
|
|
1393
|
+
"description": "Контроллер для управления токенами обновления токена доступа"
|
|
1394
|
+
},
|
|
1395
|
+
{
|
|
1396
|
+
"name": "ServiceTokens",
|
|
1397
|
+
"description": "Контроллер для управления сервисными токенами"
|
|
1398
|
+
},
|
|
1399
|
+
{
|
|
1400
|
+
"name": "Tokens",
|
|
1401
|
+
"description": "Контроллер для работы с JWT"
|
|
1402
|
+
}
|
|
1403
|
+
]
|
|
1404
|
+
}
|