Implement support ticket system with role request and bug report functionalities
- Introduced a new support ticket system allowing users to submit bug reports and role requests. - Implemented endpoints for creating, updating, and managing support tickets, including file attachments. - Enhanced Telegram bot integration to handle role requests directly within the bot, enabling admins to approve or reject requests without accessing the website. - Updated database schema to include support ticket entities and their relationships. - Improved API documentation to reflect new support ticket endpoints and their usage. - Added necessary localization for support ticket features in both Russian and English.
This commit is contained in:
+53
-1
@@ -122,6 +122,56 @@ status, createdAt }`. `expiresAt` всегда `null` (лимиты по сро
|
||||
| GET | `/api/activation/status` | user | — | `{ isActivated, pendingRequest: { id, comment, createdAt } \| null }` |
|
||||
| POST | `/api/activation/request` | user | `{ comment? }` | `{ id, comment, createdAt }` |
|
||||
|
||||
## Support (пользователь)
|
||||
|
||||
Группа `/api/support`, `RequireAuthorization()` + `IRequiresActivation` (кроме `GET /attachments/{id}`,
|
||||
который тоже требует активации, но не привязан к типу тикета). Создание баг-репорта и добавление
|
||||
комментария — `multipart/form-data` (вложения), остальное — JSON.
|
||||
|
||||
| Метод | Путь | Тело запроса | Тело ответа |
|
||||
| ----- | ----------------------------------------- | ---------------------------------------------------------------------------- | ------------- |
|
||||
| GET | `/api/support/roles` | — | `RoleDto[]` (без `admin`) — для выбора существующей роли в заявке |
|
||||
| GET | `/api/support/tickets` | query: `type?, status?, page=1, pageSize=20` | `PagedList<TicketSummaryDto>` (только свои) |
|
||||
| GET | `/api/support/tickets/{id}` | — | `TicketDetailDto` (404, если не свой) |
|
||||
| POST | `/api/support/tickets/bug-reports` | multipart: `message` + `files[]` (до 5, изображения до 5 МБ) | `TicketDetailDto` |
|
||||
| POST | `/api/support/tickets/role-requests` | `{ existingRoleId? \| (newRoleName, newRoleMaxConfigs, newRoleMaxIpLimit), justification }` | `TicketDetailDto` |
|
||||
| POST | `/api/support/tickets/{id}/comments` | multipart: `body` + `files[]` | `TicketCommentDto` |
|
||||
| POST | `/api/support/tickets/{id}/reopen` | — | `204 No Content` (только владелец, только из `Resolved`) |
|
||||
| GET | `/api/support/attachments/{id}` | — | бинарный поток с `Content-Type` вложения |
|
||||
|
||||
`TicketSummaryDto`: `{ id, userId, userName, type, status, createdAt, lastActivityAt }` — один DTO для
|
||||
своего и админского списков. `TicketDetailDto` добавляет `requestedRoleId, requestedRoleName,
|
||||
proposedRoleName, proposedMaxConfigs, proposedMaxIpLimit, comments: TicketCommentDto[]`.
|
||||
`TicketCommentDto`: `{ id, authorId, authorName, body, createdAt, attachments: TicketAttachmentDto[] }`.
|
||||
|
||||
Ровно одна из двух заявок на роль: либо `existingRoleId` (роль `admin` запрещена — `403
|
||||
Support.CannotRequestAdminRole`), либо все три поля новой роли. Заявка при существующем открытом
|
||||
запросе на роль → `409 Support.RoleRequestAlreadyPending`. `POST …/comments` на `Closed`-тикете →
|
||||
`409 Support.TicketClosed`. Вложения отдаются не статикой — `<img src>` не может передать
|
||||
`Authorization`-заголовок, фронт качает их как `Blob` через `fetch` и рендерит `Object URL`.
|
||||
|
||||
## Admin — Support
|
||||
|
||||
Группа `/api/admin/support`, `RequireAuthorization(RoleNames.Admin)` (активация не проверяется — сеяный
|
||||
админ активирован всегда).
|
||||
|
||||
| Метод | Путь | Тело запроса | Тело ответа |
|
||||
| ----- | ------------------------------------------------ | ----------------------------------- | ------------- |
|
||||
| GET | `/api/admin/support/tickets` | query: `type?, status?, page, pageSize` | `PagedList<TicketSummaryDto>` (все пользователи) |
|
||||
| GET | `/api/admin/support/tickets/{id}` | — | `TicketDetailDto` |
|
||||
| POST | `/api/admin/support/tickets/{id}/comments` | multipart: `body` + `files[]` | `TicketCommentDto` |
|
||||
| POST | `/api/admin/support/tickets/{id}/resolve` | — | `204 No Content` (любой тип, только из `Open`) |
|
||||
| POST | `/api/admin/support/tickets/{id}/close` | — | `204 No Content` (любой тип, финал) |
|
||||
| POST | `/api/admin/support/tickets/{id}/approve` | — | `204 No Content` (только `RoleRequest`/`Open`; создаёt/назначает роль) |
|
||||
| POST | `/api/admin/support/tickets/{id}/reject` | `{ reason? }` | `204 No Content` (только `RoleRequest`; `reason` уходит комментарием) |
|
||||
|
||||
`approve`/`reject` — единственный способ решить заявку на роль (нельзя одобрить через `resolve`).
|
||||
При одобрении: если заявка на существующую роль — сразу `ChangeUserRoleCommand`-эквивалент; если на
|
||||
новую — сперва создаётся `AppRole` (`IRoleService.CreateRoleAsync`), затем назначается. То же самое
|
||||
администратор может сделать **из Telegram, не заходя на сайт** — инлайн-кнопки на уведомлении о
|
||||
заявке (см. [telegram-bot.md](telegram-bot.md)); для баг-репортов в Telegram только кнопка-ссылка
|
||||
на `/admin/support/{id}` — переписка и вложения только на сайте.
|
||||
|
||||
## Admin — Activation, Roles
|
||||
|
||||
| Метод | Путь | Роль | Тело запроса | Тело ответа |
|
||||
@@ -211,6 +261,8 @@ totalConfigs, activeConfigs, totalUsedUpBytes, totalUsedDownBytes }` — счи
|
||||
| `activationRequested` | `{ requestId, userId, userName, comment, createdAt }` | `admins` |
|
||||
| `userActivated` | `{ userId }` | владельцу |
|
||||
| `newsPublished` | `{ id, title, createdAt }` | все (broadcast) |
|
||||
| `ticketCreated` | `{ ticketId, userId, userName, type }` | `admins` |
|
||||
| `ticketUpdated` | `{ ticketId }` | владельцу |
|
||||
|
||||
### Client → Server
|
||||
Клиент только слушает; группировка по пользователю происходит на сервере при подключении, по
|
||||
@@ -224,7 +276,7 @@ totalConfigs, activeConfigs, totalUsedUpBytes, totalUsedDownBytes }` — счи
|
||||
| 401 | Нет/просрочен/невалиден access-токен |
|
||||
| 403 | Нет прав по роли, либо `Auth.NotActivated` |
|
||||
| 404 | Ресурс не найден |
|
||||
| 409 | Конфликт домена: `Configs.QuotaExceeded`, дубликат имени пользователя при регистрации, уже есть `Pending`-запрос активации |
|
||||
| 409 | Конфликт домена: `Configs.QuotaExceeded`, дубликат имени пользователя при регистрации, уже есть `Pending`-запрос активации, `Support.RoleRequestAlreadyPending`, `Support.TicketClosed` |
|
||||
| 422 | Прочие управляемые ошибки, не подошедшие под коды выше |
|
||||
| 429 | Rate limit (`/api/auth/*`, `/api/auth/telegram/*`, `/sub/{token}`) |
|
||||
| 500 | Необработанное исключение (перехватывается `UseExceptionHandler()`, тело без деталей) |
|
||||
|
||||
Reference in New Issue
Block a user