{"id":27166054,"url":"https://github.com/viktorsvertoka/goit-nodejs-hw-rest-api","last_synced_at":"2026-04-08T18:31:26.013Z","repository":{"id":184830944,"uuid":"672542208","full_name":"ViktorSvertoka/goit-nodejs-hw-rest-api","owner":"ViktorSvertoka","description":"Node.js Homeworks📗","archived":false,"fork":false,"pushed_at":"2023-08-20T18:45:53.000Z","size":1522,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-03T19:29:15.483Z","etag":null,"topics":["goit","goit-nodejs-hw-rest-api","mongodb","mongoose","node","node-js","nodejs","postman"],"latest_commit_sha":null,"homepage":"https://viktorsvertoka.github.io/nodejs-homework-rest-api/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ViktorSvertoka.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2023-07-30T12:47:23.000Z","updated_at":"2024-09-23T12:40:39.000Z","dependencies_parsed_at":"2023-07-30T14:46:23.689Z","dependency_job_id":null,"html_url":"https://github.com/ViktorSvertoka/goit-nodejs-hw-rest-api","commit_stats":null,"previous_names":["viktorsvertoka/nodejs-homework-rest-api"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ViktorSvertoka/goit-nodejs-hw-rest-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ViktorSvertoka%2Fgoit-nodejs-hw-rest-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ViktorSvertoka%2Fgoit-nodejs-hw-rest-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ViktorSvertoka%2Fgoit-nodejs-hw-rest-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ViktorSvertoka%2Fgoit-nodejs-hw-rest-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ViktorSvertoka","download_url":"https://codeload.github.com/ViktorSvertoka/goit-nodejs-hw-rest-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ViktorSvertoka%2Fgoit-nodejs-hw-rest-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31568584,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"ssl_error","status_checked_at":"2026-04-08T14:31:17.202Z","response_time":54,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["goit","goit-nodejs-hw-rest-api","mongodb","mongoose","node","node-js","nodejs","postman"],"created_at":"2025-04-09T03:37:38.703Z","updated_at":"2026-04-08T18:31:25.986Z","avatar_url":"https://github.com/ViktorSvertoka.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GoIT Node.js Course Template Homework ---\u003e npm run start:dev\n\nВиконайте форк цього репозиторію для виконання домашніх завдань (2-6) Форк\nстворить репозиторій на вашому http://github.com\n\nДодайте ментора до колаборації\n\nДля кожної домашньої роботи створюйте свою гілку.\n\n- hw02\n- hw03\n- hw04\n- hw05\n- hw06\n\nКожна нова гілка для др повинна робитися з master\n\nПісля того, як ви закінчили виконувати домашнє завдання у своїй гілці, необхідно\nзробити пулл-реквест (PR). Потім додати ментора для рев'ю коду. Тільки після\nтого, як ментор заапрувить PR, ви можете виконати мердж гілки з домашнім\nзавданням у майстер.\n\nУважно читайте коментарі ментора. Виправте зауваження та зробіть коміт у гілці з\nдомашнім завданням. Зміни підтягнуться у PR автоматично після того, як ви\nвідправите коміт з виправленнями на github Після виправлення знову додайте\nментора на рев'ю коду.\n\n- При здачі домашньої роботи є посилання на PR\n- JS-код чистий та зрозумілий, для форматування використовується Prettier\n\n### Команди:\n\n- `npm start` \u0026mdash; старт сервера в режимі production\n- `npm run start:dev` \u0026mdash; старт сервера в режимі розробки (development)\n- `npm run lint` \u0026mdash; запустити виконання перевірки коду з eslint, необхідно\n  виконувати перед кожним PR та виправляти всі помилки лінтера\n- `npm lint:fix` \u0026mdash; та ж перевірка лінтера, але з автоматичними\n  виправленнями простих помилок\n\n---\n\n# Домашнє завдання 2\n\nПодивися пояснююче відео як це зробити та здавати ДЗ правильно:\n[![Title](./assets/js.png)](https://www.youtube.com/watch?v=wabSW_sz_cM ' пояснення')\n\nНаписати REST API для роботи з колекцією контактів. Для роботи з REST API\nвикористовуй [Postman] (https://www.getpostman.com/).\n\nПрочитай уважно readme в клонованому темплейті, там описаний механізм здачі\nдомашніх завдань. Та починай виконувати ДЗ\n\n## Крок 1\n\nСтвори гілку `hw02-express` з гілки master.\n\nВстанови модулі командою\n\n```bash\nnpm i\n```\n\nТакі модулі є в проекті:\n\n- [express](https://www.npmjs.com/package/express)\n- [morgan](https://www.npmjs.com/package/morgan)\n- [cors](https://www.npmjs.com/package/cors)\n\n## Крок 2\n\nУ `app.js` – веб сервер на `express` і прошарки `morgan` та `cors`. Почни\nналаштовувати раутінг для роботи з колекцією контактів.\n\nREST API повинен підтримувати такі раути.\n\n### @ GET /api/contacts\n\n- нічого не отримує\n- викликає функцію `listContacts` для роботи з json-файлом `contacts.json`\n- повертає масив всіх контактів в json-форматі зі статусом `200`\n\n### @ GET /api/contacts/:id\n\n- Не отримує `body`\n- Отримує параметр `id`\n- викликає функцію `getById` для роботи з json-файлом `contacts.json`\n- якщо такий `id` є, повертає об'єкт контакту в json-форматі зі статусом `200`\n- якщо такого `id` немає, повертає json з ключем `\"message\": \"Not found\"` і\n  статусом `404`\n\n### @ POST /api/contacts\n\n- Отримує `body` в форматі `{name, email, phone}` (усі поля обов'язкові)\n- Якщо в `body` немає якихось обов'язкових полів, повертає json з ключем\n  `{\"message\": \"missing required name field\"}` і статусом `400`\n- Якщо з `body` все добре, додає унікальний ідентифікатор в об'єкт контакту\n- Викликає функцію `addContact(body)` для збереження контакту в файлі\n  `contacts.json`\n- За результатом роботи функції повертає об'єкт з доданим `id`\n  `{id, name, email, phone}` і статусом `201`\n\n### @ DELETE /api/contacts/:id\n\n- Не отримує `body`\n- Отримує параметр `id`\n- Викликає функцію `removeContact` для роботи з json-файлом `contacts.json`\n- якщо такий `id` є, повертає json формату `{\"message\": \"contact deleted\"}` і\n  статусом `200`\n- якщо такого `id` немає, повертає json з ключем `\"message\": \"Not found\"` і\n  статусом `404`\n\n### @ PUT /api/contacts/:id\n\n- Отримує параметр `id`\n- Отримує `body` в json-форматі з оновленням будь-яких полів\n  `name, email и phone`\n- Якщо `body` немає, повертає json з ключем `{\"message\": \"missing fields\"}` і\n  статусом `400`\n- Якщо з `body` все добре, викликає функцію `updateContact(contactId, body)`.\n  (Напиши її) для поновлення контакту в файлі `contacts.json`\n- За результатом роботи функції повертає оновлений об'єкт контакту і статусом\n  `200`. В іншому випадку, повертає json з ключем `\"message\": \"Not found\"` і\n  статусом `404`\n\n## Крок 3\n\nДля маршрутів, що приймають дані (`POST` та ` PUT`), продумайте перевірку\n(валідацію) отриманих даних. Для валідації прийнятих даних використовуйте пакет\n[joi](https://github.com/sideway/joi)\n\n## Критерії прийому дз # 2-6\n\n- Створено репозиторій з домашнім завданням \u0026mdash; REST API додаток\n- При створенні репозиторія використаний\n  [бойлерплейт](https://github.com/goitacademy/nodejs-homework-template)\n- Пулл-реквест (PR) з відповідним дз відправлений менторові на перевірку\n  (посилання на PR)\n- Код відповідає технічному завданню проекта\n- При виконанні коду не виникає необроблених помилок\n- Назва змінних, властивостей і методів починається з малої літери і записуються\n  в нотації CamelCase. Використовуються англійські іменники\n- Назва функції або методу містить дієслово\n- У коді немає закоментуваних ділянок коду\n- Проект коректно працює з актуальною LTS-версією Node\n\n---\n\n# Домашнє завдання 3\n\nСтвори гілку `03-mongodb` з гілки `master`.\n\nПродовж створення REST API для роботи з колекцією контактів.\n\n## Крок 1\n\nСтвори аккаунт на [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). Після\nчого в акаунті створи новий проект і налаштуй **безкоштовний кластер**. Під час\nналаштування кластера вибери провавйдера і регіон як на скріншоті нижче. Якщо\nвибрати занадто віддалений регіон, швидкість відповіді сервера буде довше.\n\n![atlas cluster setup](./assets/atlas-cluster.jpg)\n\n## Крок 2\n\nУстанови графічний редактор\n[MongoDB Compass](https://www.mongodb.com/products/compass) для зручної роботи з\nбазою даних для MongoDB. Налаштуй підключення своєї хмарної бази даних до\nCompass. У MongoDB Atlas не забудь створити користувача з правами\nадміністратора.\n\n## Крок 3\n\nЧерез Compass створи базу даних `db-contacts` і в ній колекцію `contacts`.\nВізьми [посилання на json](./assets/contacts.json) і за допомогою Compass\nнаповни колекцію `contacts` (зроби імпорт) його вмістом.\n\n![data](./assets/json-data.png)\n\nЯкщо ви все зробили правильно, дані повинні з'явитися у вашій базі в колекції\n`contacts`\n\n![data](./assets/mongo-data.png)\n\n## Крок 4\n\nВикористовуй вихідний код [домашньої роботи #2](../homework-02/README.md) і\nзаміни зберігання контактів з json-файлу на створену тобою базу даних.\n\n- Напиши код для створення підключення до MongoDB за допомогою\n  [Mongoose](https://mongoosejs.com/).\n- При успішному підключенні виведи в консоль повідомлення\n  `\"Database connection successful\"`.\n- Обов'язково обробив помилку підключення. Виведи в консоль повідомлення помилки\n  і заверши процес використовуючи `process.exit(1)`.\n- У функціях обробки запитів заміни код CRUD-операцій над контактами з файлу, на\n  Mongoose-методи для роботи з колекцією контактів в базі даних.\n\nСхема моделі для колекції `contacts`:\n\n```js\n  {\n    name: {\n      type: String,\n      required: [true, 'Set name for contact'],\n    },\n    email: {\n      type: String,\n    },\n    phone: {\n      type: String,\n    },\n    favorite: {\n      type: Boolean,\n      default: false,\n    },\n  }\n```\n\n## Крок 5\n\nУ нас з'явилося в контактах додаткове поле статусу `favorite`, яке приймає\nлогічне значення` true` або `false`. Воно відповідає за те, що в обраному чи ні\nзнаходиться зазначений контакт. Потрібно реалізувати для оновлення статусу\nконтакту новий роутер\n\n### @ PATCH /api/contacts/:id/favorite\n\n- Отримує параметр `contactId`\n- Отримує `body` в json-форматі з оновленням поля` favorite`\n- Якщо `body` немає, повертає json з\n  ключем`{ \"message\": \"missing field favorite\"}`і статусом` 400`\n- Якщо з `body` все добре, викликає\n  функцію` updateStatusContact (contactId, body)` (напиши її) для поновлення\n  контакту в базі)\n- За результатом роботи функції повертає оновлений об'єкт контакту і статусом\n  `200`. В іншому випадку, повертає json з ключем `\" message \":\" Not found \"` і\n  статусом `404`\n\nДля роута `POST /api/contacts` внеси зміни: якщо поле `favorite` не вказали в\n`body`, то при збереженні в базу нового контакту, зроби поле `favorite` рівним\nза замовчуванням `false`\n\n---\n\n# Домашнє завдання 4\n\nСтвори гілку `04-auth` з гілки `master`.\n\nПродовж створення REST API для роботи з колекцією контактів. Додай логіку\nаутентифікації/авторизації користувача через [JWT](https://jwt.io/).\n\n## Крок 1\n\nУ коді створи схему і модель користувача для колекції `users`.\n\n```js\n{\n  password: {\n    type: String,\n    required: [true, 'Set password for user'],\n  },\n  email: {\n    type: String,\n    required: [true, 'Email is required'],\n    unique: true,\n  },\n  subscription: {\n    type: String,\n    enum: [\"starter\", \"pro\", \"business\"],\n    default: \"starter\"\n  },\n  token: String\n}\n```\n\nЗмініть схему контактів, щоб кожен користувач бачив тільки свої контакти. Для\nцього в схемі контактів додайте властивість\n\n```js\n    owner: {\n      type: Schema.Types.ObjectId,\n      ref: 'user',\n    }\n```\n\nПримітка: `'user'` - назва колекції, у якій зберігаються користувачі\n\n## Крок 2\n\n### Реєстрація\n\nСтворити ендпоінт [`/users/register`](#registration-request)\n\nЗробити валідацію всіх обов'язкових полів (email і password). При помилці\nвалідації повернути [Помилку валідації](#registration-validation-error).\n\nУ разі успішної валідації в моделі `User` створити користувача за даними, які\nпройшли валідацію. Для засолювання паролів використовуй\n[bcrypt](https://www.npmjs.com/package/bcrypt) або\n[bcryptjs](https://www.npmjs.com/package/bcryptjs)\n\n- Якщо пошта вже використовується кимось іншим, повернути\n  [Помилку Conflict](#registration-conflict-error).\n- В іншому випадку повернути\n  [Успішна відповідь](#registration-success-response).\n\n#### Registration request\n\n```shell\nPOST /users/register\nContent-Type: application/json\nRequestBody: {\n  \"email\": \"example@example.com\",\n  \"password\": \"examplepassword\"\n}\n```\n\n#### Registration validation error\n\n```shell\nStatus: 400 Bad Request\nContent-Type: application/json\nResponseBody: \u003cПомилка від Joi або іншої бібліотеки валідації\u003e\n```\n\n#### Registration conflict error\n\n```shell\nStatus: 409 Conflict\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Email in use\"\n}\n```\n\n#### Registration success response\n\n```shell\nStatus: 201 Created\nContent-Type: application/json\nResponseBody: {\n  \"user\": {\n    \"email\": \"example@example.com\",\n    \"subscription\": \"starter\"\n  }\n}\n```\n\n### Логін\n\nСтворити ендпоінт [`/users/login`](#login-request)\n\nВ моделі `User` знайти користувача за `email`.\n\nЗробити валідацію всіх обов'язкових полів (email і password). При помилці\nвалідації повернути [Помилку валідації](#validation-error-login).\n\n- В іншому випадку, порівняти пароль для знайденого користувача, якщо паролі\n  збігаються створити токен, зберегти в поточному юзера і повернути\n  [Успішна відповідь](#login-success-response).\n- Якщо пароль або імейл невірний, повернути\n  [Помилку Unauthorized](#login-auth-error).\n\n#### Login request\n\n```shell\nGET /users/login\nContent-Type: application/json\nRequestBody: {\n  \"email\": \"example@example.com\",\n  \"password\": \"examplepassword\"\n}\n```\n\n#### Login validation error\n\n```shell\nStatus: 400 Bad Request\nContent-Type: application/json\nResponseBody: \u003cПомилка від Joi або іншої бібліотеки валідації\u003e\n```\n\n#### Login success response\n\n```shell\nStatus: 200 OK\nContent-Type: application/json\nResponseBody: {\n  \"token\": \"exampletoken\",\n  \"user\": {\n    \"email\": \"example@example.com\",\n    \"subscription\": \"starter\"\n  }\n}\n```\n\n#### Login auth error\n\n```shell\nStatus: 401 Unauthorized\nResponseBody: {\n  \"message\": \"Email or password is wrong\"\n}\n```\n\n## Крок 3\n\n### Перевірка токена\n\nСтвори мідлвар для перевірки токена і додай його до всіх раутів, які повинні\nбути захищені.\n\n- Мідлвар бере токен з заголовків `Authorization`, перевіряє токен на\n  валідність.\n- У випадку помилки повернути\n  [Помилку Unauthorized](#middleware-unauthorized-error).\n- Якщо валідація пройшла успішно, отримати з токена `id` користувача. Знайти\n  користувача в базі даних з цим `id`.\n- Якщо користувач існує і токен збігається з тим, що знаходиться в базі,\n  записати його дані в `req.user` і викликати `next()`.\n- Якщо користувача з таким `id` НЕ існує або токени не збігаються, повернути\n  [Помилку Unauthorized](#middleware-unauthorized-error)\n\n#### Middleware unauthorized error\n\n```shell\nStatus: 401 Unauthorized\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Not authorized\"\n}\n```\n\n## Крок 4\n\n### Логаут\n\nСтворити ендпоінт [`/users/logout`](#logout-request)\n\nДодай в маршрут мідлвар перевірки токена.\n\n- У моделі `User` знайти користувача за `_id`.\n- Якщо користувача не існує повернути\n  [Помилку Unauthorized](#logout-unauthorized-error).\n- В іншому випадку, видалити токен у поточного юзера і повернути\n  [Успішна відповідь](#logout-success-response).\n\n#### Logout request\n\n```shell\nPOST /users/logout\nAuthorization: \"Bearer {{token}}\"\n```\n\n#### Logout unauthorized error\n\n```shell\nStatus: 401 Unauthorized\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Not authorized\"\n}\n```\n\n#### Logout success response\n\n```shell\nStatus: 204 No Content\n```\n\n## Крок 5\n\n### Поточний користувач - отримати дані юзера по токену\n\nСтворити ендпоінт [`/users/current`](#current-user-request)\n\nДодай в раут мідлвар перевірки токена.\n\n- Якщо користувача не існує повернути\n  [Помилку Unauthorized](#current-user-unauthorized-error)\n- В іншому випадку повернути [Успішну відповідь](#current-user-success-response)\n\n#### Current user request\n\n```shell\nGET /users/current\nAuthorization: \"Bearer {{token}}\"\n```\n\n#### Current user unauthorized error\n\n```shell\nStatus: 401 Unauthorized\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Not authorized\"\n}\n```\n\n#### Current user success response\n\n```shell\nStatus: 200 OK\nContent-Type: application/json\nResponseBody: {\n  \"email\": \"example@example.com\",\n  \"subscription\": \"starter\"\n}\n```\n\n## Додаткове завдання - необов'язкове\n\n- Зробити пагінацію для колекції контактів (GET /contacts?page=1\u0026limit=20).\n- Зробити фільтрацію контактів по полю обраного (GET /contacts?favorite=true)\n- Оновлення підписки (`subscription`) користувача через ендпоінт` PATCH`\n  `/users`. Підписка повинна мати одне з наступних значень\n  `['starter', 'pro', 'business']`\n\n---\n\n# Домашнє завдання 5\n\nСтвори гілку `hw05-avatars` з гілки ` master`.\n\nПродовж створення REST API для роботи з колекцією контактів. Додай можливість\nзавантаження аватарки користувача через [Multer]\n(https://github.com/expressjs/multer).\n\n## Крок 1\n\nСтвори папку `public` для роздачі статики. У цій папці зроби папку `avatars`.\nНалаштуй Express на роздачу статичних файлів з папки `public`.\n\nПоклади будь-яке зображення в папку `public/avatars` і перевір, що роздача\nстатики працює. При переході по такому URL браузер відобразить зображення.\n\n`` `Shell http://locahost:\u003cпорт\u003e/avatars/\u003cім'я файлу з розширенням\u003e `` `\n\n## Крок 2\n\nУ схему користувача додай нову властивість `avatarURL` для зберігання\nзображення.\n\n```shell\n{\n  ...\n  avatarURL: String,\n  ...\n}\n```\n\n- Використовуй пакет [gravatar](https://www.npmjs.com/package/gravatar) для\n  того, щоб при реєстрації нового користувача відразу згенерувати йому аватар по\n  його `email`.\n\n## Крок 3\n\nПри реєстрації користувача:\n\n- Створюй посилання на аватарку користувача за допомогою\n  [gravatar](https://www.npmjs.com/package/gravatar)\n- Отриманий URL збережи в поле `avatarURL` під час створення користувача\n\n## Крок 4\n\nДодай можливість поновлення аватарки, створивши ендпоінт `/users/avatars` і\nвикористовуючи метод` PATCH`.\n\n![avatar upload from postman](./assets/avatar-upload.png)\n\n```shell\n# Запит\nPATCH /users/avatars\nContent-Type: multipart/form-data\nAuthorization: \"Bearer {{token}}\"\nRequestBody: завантажений файл\n\n# Успішна відповідь\nStatus: 200 OK\nContent-Type: application/json\nResponseBody: {\n  \"avatarURL\": \"тут буде посилання на зображення\"\n}\n\n# Неуспішна відповідь\nStatus: 401 Unauthorized\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Not authorized\"\n}\n```\n\n- Створи папку `tmp` в корені проекту і зберігай в неї завантажену аватарку.\n- Оброби аватарку пакетом [jimp](https://www.npmjs.com/package/jimp) і постав\n  для неї розміри 250 на 250\n- Перенеси аватарку користувача з папки `tmp` в папку `public/avatars` і дай їй\n  унікальне ім'я для конкретного користувача.\n- Отриманий `URL` `/avatars/\u003cім'я файлу з розширенням\u003e` та збережи в поле\n  `avatarURL` користувача\n\n## Додаткове завдання - необов'язкове\n\n### 1. Написати unit-тести для контролера входу (login/signin)\n\nЗа допомогою [Jest](https://jestjs.io/ru/docs/getting-started)\n\n- відповідь повина мати статус-код 200\n- у відповіді повинен повертатися токен\n- у відповіді повинен повертатися об'єкт `user` з 2 полями `email` та\n  `subscription` з типом даних `String`\n\n---\n\n# Домашнє завдання 6\n\nСтвори гілку `hw06-email` з гілки` master`.\n\nПродовжуємо створення REST API для роботи з колекцією контактів. Додайте\nверифікацію email користувача після реєстрації за допомогою сервісу\n[SendGrid](https://sendgrid.com/).\n\n## Як процес верифікації повинен працювати\n\n1. Після реєстрації, користувач повинен отримати лист на вказану при реєстрації\n   пошту з посиланням для верифікації свого email\n2. Пройшовши по посиланню в отриманому листі, в перший раз, користувач повинен\n   отримати [Відповідь зі статусом 200](#verification-success-response), що буде\n   мати на увазі успішну верифікацію email\n3. Пройшовши по посиланню повторно користувач повинен отримати\n   [Помилку зі статусом 404](#verification-user-not-found)\n\n## Крок 1\n\n### Підготовка інтеграції з SendGrid API\n\n- Зареєструйся на [SendGrid](https://sendgrid.com/).\n- Створи email-відправника. Для цього в адміністративній панелі SendGrid зайдіть\n  в меню Marketing в підменю senders і в правому верхньому куті натисніть кнопку\n  \"Create New Sender\". Заповніть поля в запропонованій формі. Збережіть. Повинен\n  вийти наступний, як на картинці, результат, тільки з вашим email:\n\n![Sender](./assets/sender-not-verify.png)\n\nНа вказаний email має прийти лист верифікації (перевірте спам якщо не бачите\nлисти). Натисніть на посилання в ньому і завершіть процес. Результат повинен\nзміниться на:\n\n![Sender](./assets/sender-verify.png)\n\n- Тепер необхідно створити API токен доступу. Вибираємо меню \"Email API\", і\n  підменю \"Integration Guide\". Тут вибираємо \"Web API\"\n\n![Api-key](./assets/web-api.png)\n\nДалі необхідно вибрати технологію Node.js\n\n![Api-key](./assets/node.png)\n\nНа третьому кроці даємо ім'я нашого токену. Наприклад, systemcats, натискаємо\nкнопку згенерувати і отримуємо результат як на скріншоті нижче. Необхідно\nскопіювати цей токен (це важливо, тому що більше ви не зможете його подивитися).\nПісля цього завершити процес створення токена\n\n![Api-key](./assets/api-key.png)\n\n- Отриманий API-токен треба додати в `.env` файл в нашому проекті\n\n## Крок 2\n\n### Створення ендпоінта для верифікації email\n\n- додати в модель `User` два поля `verificationToken` і `verify`. Значення поля\n  `verify` рівне `false` означатиме, що його email ще не пройшов верифікацію\n\n```js\n{\n  verify: {\n    type: Boolean,\n    default: false,\n  },\n  verificationToken: {\n    type: String,\n    required: [true, 'Verify token is required'],\n  },\n}\n```\n\n- створити ендпоінт GET [`/users/verify/:verificationToken`](#\n  verification-request), де по параметру `verificationToken` ми будемо шукати\n  користувача в моделі `User`\n- якщо користувач з таким токеном не знайдений, необхідно повернути\n  [Помилку 'Not Found'](#verification-user-not-found)\n- якщо користувач знайдений - встановлюємо `verificationToken` в `null`, а поле\n  `verify` ставимо рівним `true` в документі користувача і повертаємо\n  [Успішну відповідь](#verification-success-response)\n\n### Verification request\n\n```shell\nGET /users/verify/:verificationToken\n```\n\n### Verification user Not Found\n\n```shell\nStatus: 404 Not Found\nResponseBody: {\n  message: 'User not found'\n}\n```\n\n### Verification success response\n\n```shell\nStatus: 200 OK\nResponseBody: {\n  message: 'Verification successful',\n}\n```\n\n## Крок 3\n\n### Додавання відправки email користувачу з посиланням для верифікації\n\nПри створенні користувача при реєстрації:\n\n- створити `verificationToken` для користувача і записати його у БД (для\n  генерації токена використовуйте пакет\n  [uuid](https://www.npmjs.com/package/uuid) або\n  [nanoid](https://www.npmjs.com/package/nanoid))\n- відправити email на пошту користувача і вказати посилання для верифікації\n  email'а ( `/users/verify/:verificationToken`) в повідомленні\n- Так само необхідно враховувати, що тепер логін користувача не дозволений, якщо\n  не верифікувано email\n\n## Крок 4\n\n### Додавання повторної відправки email користувачу з посиланням для верифікації\n\nНеобхідно передбачити, варіант, що користувач може випадково видалити лист. Воно\nможе не дійти з якоїсь причини до адресата. Наш сервіс відправки листів під час\nреєстрації видав помилку і т.д.\n\n#### @ POST /users/verify\n\n- Отримує `body` у форматі `{email}`\n- Якщо в `body` немає обов'язкового поля `email`, повертає json з ключем\n  `{\"message\":\"missing required field email\"}` і статусом `400`\n- Якщо з `body` все добре, виконуємо повторну відправку листа з\n  `verificationToken` на вказаний email, але тільки якщо користувач не\n  верифікований\n- Якщо користувач вже пройшов верифікацію відправити json з ключем\n  `{\"message\":\"Verification has already been passed\"}` зі статусом\n  `400 Bad Request`\n\n#### Resending a email request\n\n````shell\nPOST /users/verify\nContent-Type: application/json\nRequestBody: {\n  \"email\": \"example@example.com\"\n}\n`` `\n\n#### Resending a email validation error\n\n```shell\nStatus: 400 Bad Request\nContent-Type: application/json\nResponseBody: \u003cПомилка від Joi або іншої бібліотеки валідації\u003e\n````\n\n#### Resending a email success response\n\n```shell\nStatus: 200 Ok\nContent-Type: application/json\nResponseBody: {\n  \"message\": \"Verification email sent\"\n}\n```\n\n#### Resend email for verified user\n\n```shell\nStatus: 400 Bad Request\nContent-Type: application/json\nResponseBody: {\n  message: \"Verification has already been passed\"\n}\n```\n\n\u003e Примітка: Як альтернативу SendGrid можна використовувати пакет\n\u003e [nodemailer](https://www.npmjs.com/package/nodemailer)\n\n## Додаткове завдання - необов'язкове\n\n### 1. Напишіть dockerfile для вашої програми\n\n\u003c!-- docker build . --\u003e\n\u003c!-- docker images --\u003e\n\u003c!-- docker run + id --\u003e\n\u003c!-- docker ps --\u003e\n\u003c!-- docker stop + id --\u003e\n\u003c!-- docker start + id --\u003e\n\nyarn add @sendgrid/mail\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviktorsvertoka%2Fgoit-nodejs-hw-rest-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fviktorsvertoka%2Fgoit-nodejs-hw-rest-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fviktorsvertoka%2Fgoit-nodejs-hw-rest-api/lists"}