{"id":21175526,"url":"https://github.com/capcom6-learning/netology-ndjs-diplom","last_synced_at":"2025-03-14T18:22:44.204Z","repository":{"id":247721113,"uuid":"826296228","full_name":"capcom6-learning/netology-ndjs-diplom","owner":"capcom6-learning","description":null,"archived":false,"fork":false,"pushed_at":"2024-12-17T06:38:13.000Z","size":3405,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-21T11:28:08.408Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/capcom6-learning.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-07-09T12:36:12.000Z","updated_at":"2024-12-17T06:38:14.000Z","dependencies_parsed_at":"2024-11-20T16:59:47.274Z","dependency_job_id":"d8d09868-1a58-48a3-b634-700bdf4fdb7a","html_url":"https://github.com/capcom6-learning/netology-ndjs-diplom","commit_stats":null,"previous_names":["capcom6/netology-ndjs-diplom","capcom6-learning/netology-ndjs-diplom"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capcom6-learning%2Fnetology-ndjs-diplom","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capcom6-learning%2Fnetology-ndjs-diplom/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capcom6-learning%2Fnetology-ndjs-diplom/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/capcom6-learning%2Fnetology-ndjs-diplom/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/capcom6-learning","download_url":"https://codeload.github.com/capcom6-learning/netology-ndjs-diplom/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243624090,"owners_count":20321029,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T16:59:47.585Z","updated_at":"2025-03-14T18:22:44.173Z","avatar_url":"https://github.com/capcom6-learning.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Дипломный проект на курсе «Backend-разработка на Node.js»\n\n## Описание проекта\n\nДипломный проект представляет собой сайт-агрегатор просмотра и бронирования гостиниц. Ваша задача заключается в разработке бэкенда для сайта-агрегатора с реализацией возможности бронирования гостиниц на диапазон дат.\n\n## Цели проекта\n\n1. Разработка публичного API.\n2. Разработка API пользователя.\n3. Разработка API администратора.\n4. Разработка чата консультанта.\n\n## Технологический стек\n\n- Node.js;\n- Nest.js;\n- MongoDB;\n- WebSocket.\n\n## Допущения\n\nОплату бронирования реализовывать не нужно.\n\n## Глоссарий\n\nВ документе приводятся описания разных интерфейсов и типов. Для упрощения описания в этом разделе приводятся общие типы.\n\n```ts\ntype ID = string | ObjectId;\n```\n\n## 1. Описание базовых модулей\n\nБазовые модули используются для описания бизнес-логики и хранения данных.\n\n### 1.1. Модуль «Пользователи»\n\nМодуль «Пользователи» предназначается для создания, хранения и поиска профилей пользователей.\n\nМодуль «Пользователи» используется функциональными модулями для регистрации и аутентификации.\n\nДанные пользователя должны храниться в MongoDB.\n\nМодель данных `User` пользователя должна содержать поля:\n\n| Название     |    Тип     | Обязательное | Уникальное | По умолчанию |\n| ------------ | :--------: | :----------: | :--------: | :----------: |\n| \\_id         | `ObjectId` |      да      |     да     |              |\n| email        |  `string`  |      да      |     да     |              |\n| passwordHash |  `string`  |      да      |    нет     |              |\n| name         |  `string`  |      да      |    нет     |              |\n| contactPhone |  `string`  |     нет      |    нет     |              |\n| role         |  `string`  |      да      |    нет     |   `client`   |\n\n---\n\nМодуль «Пользователи» должен быть реализован в виде NestJS-модуля и экспортировать сервисы с интерфейсами:\n\n```ts\ninterface SearchUserParams {\n  limit: number;\n  offset: number;\n  email: string;\n  name: string;\n  contactPhone: string;\n}\ninterface IUserService {\n  create(data: Partial\u003cUser\u003e): Promise\u003cUser\u003e;\n  findById(id: ID): Promise\u003cUser\u003e;\n  findByEmail(email: string): Promise\u003cUser\u003e;\n  findAll(params: SearchUserParams): Promise\u003cUser[]\u003e;\n}\n```\n\nПоле `role` может принимать одно из значений:\n\n- `client`,\n- `admin`,\n- `manager`.\n\nПри поиске `IUserService.findAll()` поля `email`, `name` и `contactPhone` должны проверяться на частичное совпадение.\n\n### 1.2. Модуль «Гостиницы»\n\nМодуль «Гостиницы» предназначается для хранения и поиска гостиниц и комнат.\n\nМодуль «Гостиницы» используется функциональными модулями для показа списка мест для бронирования, а также для их добавления, включения и выключения.\n\nДанные должны храниться в MongoDB.\n\nМодель данных `Hotel` должна содержать поля:\n\n| Название    |    Тип     | Обязательное | Уникальное | По умолчанию |\n| ----------- | :--------: | :----------: | :--------: | :----------: |\n| \\_id        | `ObjectId` |      да      |     да     |              |\n| title       |  `string`  |      да      |     да     |              |\n| description |  `string`  |     нет      |    нет     |              |\n| createdAt   |   `Date`   |      да      |    нет     |              |\n| updatedAt   |   `Date`   |      да      |    нет     |              |\n\nМодель данных `HotelRoom` должна содержать поля:\n\n| Название    |    Тип     | Обязательное | Уникальное | По умолчанию |\n| ----------- | :--------: | :----------: | :--------: | :----------: |\n| \\_id        | `ObjectId` |      да      |     да     |              |\n| hotel       | `ObjectId` |      да      |    нет     |              |\n| description |  `string`  |     нет      |    нет     |              |\n| images      | `string[]` |     нет      |    нет     |     `[]`     |\n| createdAt   |   `Date`   |      да      |    нет     |              |\n| updatedAt   |   `Date`   |      да      |    нет     |              |\n| isEnabled   | `boolean`  |      да      |    нет     |    `true`    |\n\nСвойство `hotel` должно [ссылаться](https://mongoosejs.com/docs/populate.html) на модель `Hotel`.\n\n---\n\nМодуль «Гостиницы» должен быть реализован в виде NestJS-модуля и экспортировать сервисы с интерфейсами:\n\n```ts\ninterface SearchHotelParams {\n  limit: number;\n  offset: number;\n  title: string;\n}\n\ninterface UpdateHotelParams {\n  title: string;\n  description: string;\n}\n\ninterface IHotelService {\n  create(data: any): Promise\u003cHotel\u003e;\n  findById(id: ID): Promise\u003cHotel\u003e;\n  search(params: SearchHotelParams): Promise\u003cHotel[]\u003e;\n  update(id: ID, data: UpdateHotelParams): Promise\u003cHotel\u003e;\n}\n\ninterface SearchRoomsParams {\n  limit: number;\n  offset: number;\n  hotel: ID;\n  isEnabled?: boolean;\n}\n\ninterface HotelRoomService {\n  create(data: Partial\u003cHotelRoom\u003e): Promise\u003cHotelRoom\u003e;\n  findById(id: ID): Promise\u003cHotelRoom\u003e;\n  search(params: SearchRoomsParams): Promise\u003cHotelRoom[]\u003e;\n  update(id: ID, data: Partial\u003cHotelRoom\u003e): Promise\u003cHotelRoom\u003e;\n}\n```\n\nВ методе `search` флаг `isEnabled` может принимать только boolean значения или может быть не передан, тогда должны вернутся все записи:\n\n- `true` — флаг должен использоваться в фильтрации;\n- `undefined` — если не передан параметр, флаг должен игнорироваться.\n\n### 1.3. Модуль «Брони»\n\nМодуль «Брони» предназначен для хранения и получения броней гостиниц конкретного пользователя.\n\nМодуль «Брони» **не должен** использовать модуль «Пользователи» и модуль «Гостиницы» для получения данных.\n\nМодуль «Брони» **не должен** хранить данные пользователей и гостиниц.\n\nМодуль «Брони» **должен** использовать соединение с базой данных.\n\nДанные должны храниться в MongoDB.\n\nМодель данных `Reservation` должна содержать поля:\n\n| Название  |    Тип     | Обязательное | Уникальное | По умолчанию |\n| --------- | :--------: | :----------: | :--------: | :----------: |\n| \\_id      | `ObjectId` |      да      |     да     |              |\n| userId    | `ObjectId` |      да      |    нет     |              |\n| hotelId   | `ObjectId` |      да      |    нет     |              |\n| roomId    | `ObjectId` |      да      |    нет     |              |\n| dateStart |   `Date`   |      да      |    нет     |              |\n| dateEnd   |   `Date`   |      да      |    нет     |              |\n\n---\n\nМодуль «Брони» должен быть реализован в виде NestJS-модуля и экспортировать сервисы с интерфейсами:\n\n```ts\ninterface ReservationDto {\n  userId: ID;\n  hotelId: ID;\n  roomId: ID;\n  dateStart: Date;\n  dateEnd: Date;\n}\n\ninterface ReservationSearchOptions {\n  userId: ID;\n  dateStart: Date;\n  dateEnd: Date;\n}\ninterface IReservation {\n  addReservation(data: ReservationDto): Promise\u003cReservation\u003e;\n  removeReservation(id: ID): Promise\u003cvoid\u003e;\n  getReservations(\n    filter: ReservationSearchOptions\n  ): Promise\u003cArray\u003cReservation\u003e\u003e;\n}\n```\n\nМетод `IReservation.addReservation` должен проверять, доступен ли номер на заданную дату.\n\n### 1.4. Модуль «Чат техподдержки»\n\nМодуль «Чат техподдержки» предназначается для хранения обращений в техподдержку и сообщений в чате обращения.\n\nМодуль «Чат техподдержки» используется функциональными модулями для реализации возможности общения пользователей с поддержкой.\n\nДанные чатов должны храниться в MongoDB.\n\nМодель данных чата `SupportRequest` должна содержать поля:\n\n| Название  |     Тип     | Обязательное | Уникальное |\n| --------- | :---------: | :----------: | :--------: |\n| \\_id      | `ObjectId`  |      да      |     да     |\n| user      | `ObjectId`  |      да      |    нет     |\n| createdAt |   `Date`    |      да      |    нет     |\n| messages  | `Message[]` |     нет      |    нет     |\n| isActive  |   `bool`    |     нет      |    нет     |\n\nМодель сообщения `Message` должна содержать поля:\n\n| Название |    Тип     | Обязательное | Уникальное |\n| -------- | :--------: | :----------: | :--------: |\n| \\_id     | `ObjectId` |      да      |     да     |\n| author   | `ObjectId` |      да      |    нет     |\n| sentAt   |   `Date`   |      да      |    нет     |\n| text     |  `string`  |      да      |    нет     |\n| readAt   |   `Date`   |     нет      |    нет     |\n\nСообщение считается прочитанным, когда поле `readAt` не пустое.\n\n---\n\nМодуль «Чат техподдержки» должен быть реализован в виде NestJS-модуля и должен экспортировать сервисы с интерфейсами:\n\n```ts\ninterface CreateSupportRequestDto {\n  user: ID;\n  text: string;\n}\n\ninterface SendMessageDto {\n  author: ID;\n  supportRequest: ID;\n  text: string;\n}\ninterface MarkMessagesAsReadDto {\n  user: ID;\n  supportRequest: ID;\n  createdBefore: Date;\n}\n\ninterface GetChatListParams {\n  user: ID | null;\n  isActive: bool;\n}\n\ninterface ISupportRequestService {\n  findSupportRequests(params: GetChatListParams): Promise\u003cSupportRequest[]\u003e;\n  sendMessage(data: SendMessageDto): Promise\u003cMessage\u003e;\n  getMessages(supportRequest: ID): Promise\u003cMessage[]\u003e;\n  subscribe(\n    handler: (supportRequest: SupportRequest, message: Message) =\u003e void\n  ): () =\u003e void;\n}\n\ninterface ISupportRequestClientService {\n  createSupportRequest(data: CreateSupportRequestDto): Promise\u003cSupportRequest\u003e;\n  markMessagesAsRead(params: MarkMessagesAsReadDto);\n  getUnreadCount(supportRequest: ID): Promise\u003cnumber\u003e;\n}\n\ninterface ISupportRequestEmployeeService {\n  markMessagesAsRead(params: MarkMessagesAsReadDto);\n  getUnreadCount(supportRequest: ID): Promise\u003cnumber\u003e;\n  closeRequest(supportRequest: ID): Promise\u003cvoid\u003e;\n}\n```\n\n---\n\n1. Метод `ISupportRequestClientService.getUnreadCount` должен возвращать количество сообщений, которые были отправлены любым сотрудником поддержки и не отмечены прочитанным.\n2. Метод `ISupportRequestClientService.markMessagesAsRead` должен выставлять текущую дату в поле readAt всем сообщениям, которые не были прочитаны и были отправлены не пользователем.\n3. Метод `ISupportRequestEmployeeService.getUnreadCount` должен возвращать количество сообщений, которые были отправлены пользователем и не отмечены прочитанными.\n4. Метод `ISupportRequestEmployeeService.markMessagesAsRead` должен выставлять текущую дату в поле readAt всем сообщениям, которые не были прочитаны и были отправлены пользователем.\n5. Метод `ISupportRequestEmployeeService.closeRequest` должен менять флаг `isActive` на `false`.\n6. Оповещения должны быть реализованы через механизм `EventEmitter`.\n\n## 2. Описание модулей WEB API\n\n## 2.1. API Модуля «Гостиницы»\n\nДолжно быть оформлено в виде отдельного NestJS-модуля.\n\n### **Ограничения**\n\nЕсли пользователь не аутентифицирован или его роль `client`, то при поиске всегда должен использоваться флаг `isEnabled: true`.\n\n### **2.1.1. Поиск номеров**\n\n#### **Описание**\n\nОсновной API для поиска номеров.\n\n#### **Адрес**\n\n```http\nGET /api/common/hotel-rooms\n```\n\n#### **Query-параметры**\n\n- limit — количество записей в ответе;\n- offset — сдвиг от начала списка;\n- hotel — ID гостиницы для фильтра.\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"description\": string,\n    \"images\": [string],\n    \"hotel\": {\n      \"id\": string,\n      \"title\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно всем пользователям, включая неаутентифицированных.\n\n### **2.1.2. Информация о конкретном номере**\n\n#### **Описание**\n\nПолучение подробной информации о номере.\n\n#### **Адрес**\n\n```http\nGET /api/common/hotel-rooms/:id\n```\n\n#### **Query-параметры**\n\nОтсутствуют.\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"description\": string,\n  \"images\": [string],\n  \"hotel\": {\n    \"id\": string,\n    \"title\": string,\n    \"description\": string\n  }\n}\n```\n\n#### **Доступ**\n\nДоступно всем пользователям, включая неаутентифицированных.\n\n### **2.1.3. Добавление гостиницы**\n\n#### **Описание**\n\nДобавление гостиницы администратором.\n\n#### **Адрес**\n\n```http\nPOST /api/admin/hotels/\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"title\": string,\n  \"description\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"title\": string,\n  \"description\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### **2.1.4. Получение списка гостиниц**\n\n#### **Описание**\n\nПолучение списка гостиниц администратором.\n\n#### **Адрес**\n\n```http\nGET /api/admin/hotels/\n```\n\n#### **Query-параметры**\n\n- limit - количество записей в ответе.\n- offset - сдвиг от начала списка.\n- title - фильтр по полю.\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"title\": string,\n  \"description\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### **2.1.5. Изменение описания гостиницы**\n\n#### **Описание**\n\nИзменение описания гостиницы администратором.\n\n#### **Адрес**\n\n```http\nPUT /api/admin/hotels/:id\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"title\": string,\n  \"description\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"title\": string,\n  \"description\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### **2.1.6. Добавление номера**\n\n#### **Описание**\n\nДобавление номера гостиницы администратором.\n\n#### **Адрес**\n\n```http\nPOST /api/admin/hotel-rooms/\n```\n\n#### **Body-параметры**\n\nЭтот запрос предполагает загрузку файлов и должен использовать формат `multipart/form-data`.\n\n```form-data\ndescription: string\nhotelId: string\nimages[]: File\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"description\": string,\n  \"images\": [string],\n  \"isEnabled\": boolean,\n  \"hotel\": {\n    \"id\": string,\n    \"title\": string,\n    \"description\": string\n  }\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### **2.1.7. Изменение описания номера**\n\n#### **Описание**\n\nИзменение описания номера гостиницы администратором.\n\n#### **Адрес**\n\n```http\nPUT /api/admin/hotel-rooms/:id\n```\n\n#### **Body-параметры**\n\nЭтот запрос предполагает загрузку файлов и дожен использовать формат `multipart/form-data`.\n\n```form-data\ndescription: string\nhotelId: string\nisEnabled: boolean\nimages[]: File | string\n```\n\nПри обновлении может быть отправлен одновременно список ссылок на уже загруженные картинки и список файлов с новыми картинками.\n\nПри использовании [`multer`](https://docs.nestjs.com/techniques/file-upload) список загруженных файлов можно получить через `@UploadedFiles()`. Этот список нужно объединить со списком, который пришёл в `body`.\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"description\": string,\n  \"images\": [string],\n  \"isEnabled\": boolean,\n  \"hotel\": {\n    \"id\": string,\n    \"title\": string,\n    \"description\": string\n  }\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### 2.2. API Модуля «Бронирование»\n\nДолжно быть оформлено в виде отдельного NestJS-модуля.\n\n### **2.2.1. Бронирование номера клиентом**\n\n#### **Описание**\n\nСоздаёт бронь на номер на выбранную дату для текущего пользователя.\n\n#### **Адрес**\n\n```http\nPOST /api/client/reservations\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"hotelRoom\": string,\n  \"startDate\": string,\n  \"endDate\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"startDate\": string,\n  \"endDate\": string,\n  \"hotelRoom\": {\n    \"description\": string,\n    \"images\": [string]\n  },\n  \"hotel\": {\n    \"title\": string,\n    \"description\": string\n  }\n}\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `client`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `client`;\n- `400` - если номера с указанным ID не существует или он отключён.\n\n### **2.2.2. Список броней текущего пользователя**\n\n#### **Описание**\n\nСписок броней текущего пользователя.\n\n#### **Адрес**\n\n```http\nGET /api/client/reservations\n```\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"startDate\": string,\n    \"endDate\": string,\n    \"hotelRoom\": {\n      \"description\": string,\n      \"images\": [string]\n    },\n    \"hotel\": {\n      \"title\": string,\n      \"description\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `client`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `client`.\n\n### **2.2.3. Отмена бронирования клиентом**\n\n#### **Описание**\n\nОтменяет бронь пользователя.\n\n#### **Адрес**\n\n```http\nDELETE /api/client/reservations/:id\n```\n\n#### **Формат ответа**\n\nПустой ответ.\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `client`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `client`;\n- `403` - если `ID` текущего пользователя не совпадает с `ID` пользователя в брони;\n- `400` - если брони с указанным ID не существует.\n\n### **2.2.4. Список броней конкретного пользователя**\n\n#### **Описание**\n\nСписок броней конкретного пользователя.\n\n#### **Адрес**\n\n```http\nGET /api/manager/reservations/:userId\n```\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"startDate\": string,\n    \"endDate\": string,\n    \"hotelRoom\": {\n      \"description\": string,\n      \"images\": [string]\n    },\n    \"hotel\": {\n      \"title\": string,\n      \"description\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `manager`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `manager`.\n\n### **2.2.5. Отмена бронирования менеджером**\n\n#### **Описание**\n\nОтменяет бронь пользователя по id брони.\n\n#### **Адрес**\n\n```http\nDELETE /api/manager/reservations/:id\n```\n\n#### **Формат ответа**\n\nПустой ответ.\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям с ролью `manager`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `manager`;\n- `400` - если брони с указанным ID не существует.\n\n## 2.3. API Модуля «Аутентификация и авторизация»\n\nДолжно быть оформлено в виде отдельного NestJS-модуля.\n\nМодуль «Аутентификация и авторизация» предназначен для:\n\n- управления сессией пользователя,\n- регистрации пользователей.\n\nХранение сессии должно реализовываться посредством библиотеки passport.js с хранением сессии в памяти приложения.\n\nАутентификация пользователя производится с помощью модуля «Пользователи». Каждому пользователю назначается одна из ролей - клиент, администратор, консультант.\n\n### **2.3.1. Вход**\n\n#### **Описание**\n\nСтартует сессию пользователя и выставляет Cookies.\n\n#### **Адрес**\n\n```http\nPOST /api/auth/login\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"email\": string,\n  \"password\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"email\": string,\n  \"name\": string,\n  \"contactPhone\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только не аутентифицированным пользователям.\n\n#### **Ошибки**\n\n- `401` - если пользователя с указанным email не существует или пароль неверный.\n\n### **2.3.2. Выход**\n\n#### **Описание**\n\nЗавершает сессию пользователя и удаляет Cookies.\n\n#### **Адрес**\n\n```http\nPOST /api/auth/logout\n```\n\n#### **Формат ответа**\n\nПустой ответ.\n\n#### **Доступ**\n\nДоступно только аутентифицированным пользователям.\n\n### **2.3.3. Регистрация**\n\n#### **Описание**\n\nПозволяет создать пользователя с ролью `client` в системе.\n\n#### **Адрес**\n\n```http\nPOST /api/client/register\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"email\": string,\n  \"password\": string,\n  \"name\": string,\n  \"contactPhone\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"email\": string,\n  \"name\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только не аутентифицированным пользователям.\n\n#### **Ошибки**\n\n- `400` - если email уже занят.\n\n## 2.4. API Модуля «Управление пользователями»\n\n### **2.4.1. Создание пользователя**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `admin` создать пользователя в системе.\n\n#### **Адрес**\n\n```http\nPOST /api/admin/users/\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"email\": string,\n  \"password\": string,\n  \"name\": string,\n  \"contactPhone\": string,\n  \"role\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"email\": string,\n  \"name\": string,\n  \"contactPhone\": string,\n  \"role\": string\n}\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `admin`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не `admin`.\n\n### **2.4.2. Получение списка пользователей**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `admin` создать пользователя в системе.\n\n#### **Адрес**\n\n```http\nGET /api/admin/users/\nGET /api/manager/users/\n```\n\n#### **Query-параметры**\n\n- limit - количество записей в ответе;\n- offset - сдвиг от начала списка;\n- name - фильтр по полю;\n- email - фильтр по полю;\n- contactPhone - фильтр по полю.\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"email\": string,\n    \"name\": string,\n    \"contactPhone\": string\n  }\n]\n```\n\n#### **Доступ**\n\n```http\nGET /api/admin/users/\n```\n\nДоступно только пользователям с ролью `admin`.\n\n```http\nGET /api/manager/users/\n```\n\nДоступно только пользователям с ролью `manager`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n## 2.5. API модуля «Чат с техподдрежкой»\n\n### **2.5.1. Создание обращения в поддержку**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `client` создать обращение в техподдержку.\n\n#### **Адрес**\n\n```http\nPOST /api/client/support-requests/\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"text\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"createdAt\": string,\n    \"isActive\": boolean,\n    \"hasNewMessages\": boolean\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `client`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.2. Получение списка обращений в поддержку для клиента**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `client` получить список обращений для текущего пользователя.\n\n#### **Адрес**\n\n```http\nGET /api/client/support-requests/\n```\n\n#### **Query-параметры**\n\n- limit - количество записей в ответе;\n- offset - сдвиг от начала списка;\n- isActive - фильтр по полю.\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"createdAt\": string,\n    \"isActive\": boolean,\n    \"hasNewMessages\": boolean\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `client`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.3. Получение списка обращений в поддержку для менеджера**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `manager` получить список обращений от клиентов.\n\n#### **Адрес**\n\n```http\nGET /api/manager/support-requests/\n```\n\n#### **Query-параметры**\n\n- limit - количество записей в ответе;\n- offset - сдвиг от начала списка;\n- isActive - фильтр по полю.\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"createdAt\": string,\n    \"isActive\": boolean,\n    \"hasNewMessages\": boolean,\n    \"client\": {\n      \"id\": string,\n      \"name\": string,\n      \"email\": string,\n      \"contactPhone\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `manager`.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.4. Получение истории сообщений из обращения в техподдержку**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `manager` или `client` получить все сообщения из чата.\n\n#### **Адрес**\n\n```http\nGET /api/common/support-requests/:id/messages\n```\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"createdAt\": string,\n    \"text\": string,\n    \"readAt\": string,\n    \"author\": {\n      \"id\": string,\n      \"name\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `manager` и пользователю с ролью `client`, который создал обращение.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.5. Отправка сообщения**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `manager` или `client` отправлять сообщения в чат.\n\n#### **Адрес**\n\n```http\nPOST /api/common/support-requests/:id/messages\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"text\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n[\n  {\n    \"id\": string,\n    \"createdAt\": string,\n    \"text\": string,\n    \"readAt\": string,\n    \"author\": {\n      \"id\": string,\n      \"name\": string\n    }\n  }\n]\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `manager` и пользователю с ролью `client`, который создал обращение.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.6. Отправка события, что сообщения прочитаны**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `manager` или `client` отправлять отметку, что сообщения прочитаны.\n\n#### **Адрес**\n\n```http\nPOST /api/common/support-requests/:id/messages/read\n```\n\n#### **Body-параметры**\n\n```json\n{\n  \"createdBefore\": string\n}\n```\n\n#### **Формат ответа**\n\n```json\n{\n  \"success\": true\n}\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `manager` и пользователю с ролью `client`, который создал обращение.\n\n#### **Ошибки**\n\n- `401` - если пользователь не аутентифицирован;\n- `403` - если роль пользователя не подходит.\n\n### **2.5.7. Подписка на сообщения из чата техподдержки**\n\n#### **Описание**\n\nПозволяет пользователю с ролью `manager` или `client` получать новые сообщения в чате через WebSocket.\n\n#### **Команда**\n\nmessage: subscribeToChat\npayload: chatId\n\n#### **Формат ответа**\n\n```json\n{\n  \"id\": string,\n  \"createdAt\": string,\n  \"text\": string,\n  \"readAt\": string,\n  \"author\": {\n    \"id\": string,\n    \"name\": string\n  }\n}\n```\n\n#### **Доступ**\n\nДоступно только пользователям с ролью `manager` и пользователю с ролью `client`, который создал обращение.\n\n## Запуск приложения\n\nДля запуска приложения в корне проекта должны находиться следующие файлы:\n\n- `package.json` и `package-lock.json` с описанными зависимостями,\n- `Dockerfile` для сборки образа приложения,\n- `docker-compose.yaml` с сервисом приложения и сервисом MondoDB,\n- `README.me` с описанием проекта и вариантами его запуска.\n\nНастройка параметров приложения должна производиться через переменные окружения. Это требование как для запуска в окружении хоста, так и при работе с Docker.\n\nСписок переменных окружения должен быть описан в файле `.env-example`. Этот файл не должен содержать значений. Пример файла:\n\n```bash\nHTTP_HOST=\nHTTP_PORT=\nMONGO_URL=\n```\n\nДля запуска приложения должен использоваться скрипт `npm start`, описанный в `package.json`.\n\n## Как задавать вопросы руководителю по дипломной работе\n\n1. Если у вас возник вопрос, попробуйте сначала самостоятельно найти ответ в интернете. Навык поиска информации пригодится вам в любой профессиональной деятельности. Если ответ не нашёлся, можно уточнить у руководителя по дипломной работе.\n2. Если у вас набирается несколько вопросов, присылайте их в виде нумерованного списка. Так дипломному руководителю будет проще отвечать на каждый из них.\n3. Для лучшего понимания контекста прикрепите к вопросу скриншоты и стрелкой укажите, что именно вызывает вопрос. Программу для создания скриншотов можно скачать [по ссылке](https://app.prntscr.com/ru/).\n4. По возможности задавайте вопросы в комментариях к коду.\n5. Формулируйте свои вопросы чётко, дополняя их деталями. На сообщения «Ничего не работает», «Всё сломалось» дипломный руководитель не сможет дать комментарии без дополнительных уточнений. Это затянет процесс получения ответа. \n6. Постарайтесь набраться терпения в ожидании ответа на свои вопросы. Дипломные руководители Нетологии – практикующие разработчики, поэтому они не всегда могут отвечать моментально. Зато их практика даёт возможность делиться с вами не только теорией, но и ценным прикладным опытом.  \n\nРекомендации по работе над дипломом:\n\n1. Не откладывайте надолго начало работы над дипломом. В таком случае у вас останется больше времени на получение рекомендаций от руководителя и доработку диплома.\n2. Разбейте работу над дипломом на части и выполняйте их поочерёдно. Вы будете успевать учитывать комментарии от руководителя и не терять мотивацию на полпути. ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapcom6-learning%2Fnetology-ndjs-diplom","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcapcom6-learning%2Fnetology-ndjs-diplom","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcapcom6-learning%2Fnetology-ndjs-diplom/lists"}