From b31bdf6b9bbdd2814c3a98533ffad3e1fa16fddb Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Fri, 30 Jun 2023 22:19:39 +0300 Subject: [PATCH 1/9] homework --- homework-01/.eslintignore | 1 + homework-01/.eslintrc.js | 12 ++ homework-01/.gitignore | 4 + homework-01/README.en.md | 164 ----------------------- homework-01/README.es.md | 164 ----------------------- homework-01/README.md | 169 +----------------------- homework-01/README.pl.md | 164 ----------------------- homework-01/README.ua.md | 165 ----------------------- homework-01/controllers/contacts.js | 56 ++++++++ homework-01/helpers/CtrlWrapper.js | 13 ++ homework-01/helpers/HttpErrors.js | 7 + homework-01/helpers/index.js | 7 + homework-01/middlewares/index.js | 5 + homework-01/middlewares/validateBody.js | 17 +++ homework-01/models/contacts.js | 82 ++++++++++++ homework-01/{ => models}/contacts.json | 38 +++++- homework-01/nodemon.json | 3 + homework-01/routes/api/contacts.js | 21 +++ homework-01/server.js | 6 + 19 files changed, 270 insertions(+), 828 deletions(-) create mode 100644 homework-01/.eslintignore create mode 100644 homework-01/.eslintrc.js create mode 100644 homework-01/.gitignore delete mode 100644 homework-01/README.en.md delete mode 100644 homework-01/README.es.md delete mode 100644 homework-01/README.pl.md delete mode 100755 homework-01/README.ua.md create mode 100644 homework-01/controllers/contacts.js create mode 100644 homework-01/helpers/CtrlWrapper.js create mode 100644 homework-01/helpers/HttpErrors.js create mode 100644 homework-01/helpers/index.js create mode 100644 homework-01/middlewares/index.js create mode 100644 homework-01/middlewares/validateBody.js create mode 100644 homework-01/models/contacts.js rename homework-01/{ => models}/contacts.json (64%) create mode 100644 homework-01/nodemon.json create mode 100644 homework-01/routes/api/contacts.js create mode 100644 homework-01/server.js diff --git a/homework-01/.eslintignore b/homework-01/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/homework-01/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/homework-01/.eslintrc.js b/homework-01/.eslintrc.js new file mode 100644 index 0000000..d799332 --- /dev/null +++ b/homework-01/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + env: { + commonjs: true, + es2021: true, + node: true, + }, + extends: ['standard', 'prettier'], + parserOptions: { + ecmaVersion: 12, + }, + rules: {}, +} diff --git a/homework-01/.gitignore b/homework-01/.gitignore new file mode 100644 index 0000000..8877fc5 --- /dev/null +++ b/homework-01/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.idea +.vscode \ No newline at end of file diff --git a/homework-01/README.en.md b/homework-01/README.en.md deleted file mode 100644 index 7d96525..0000000 --- a/homework-01/README.en.md +++ /dev/null @@ -1,164 +0,0 @@ -**Read in other languages: [Russian](README.md), [Ukrainian](README.ua.md).** - -# Homework 1 - -## Step 1 - -- Initialize npm in the project -- In the root of the project, create a file `index.js` -- Install package [nodemon](https://www.npmjs.com/package/nodemon) as development dependency (devDependencies) -- In `package.json` file add "scripts" to run `index.js` -- `start` script that starts `index.js` with `node` -- `start:dev` script that starts `index.js` with `nodemon` - -## Step 2 - -Create a folder `db` in the root of the project. To store contacts, download and use the [contacts.json](./contacts.json) file, putting it in the `db` folder. - -At the root of the project, create a `contacts.js` file. - -- Make imports of modules `fs` and `path` to work with the file system -- Create a `contactsPath` variable and put the path to the `contacts.json` file in it. To compose a path, use the methods of the `path` module -- Add functions to work with a collection of contacts. In functions, use the `fs` module and its `readFile()` and `writeFile()` methods -- Make export of created functions via `module.exports` - -```js -// contacts.js - -/* - * Uncomment and write down the value - * const contactsPath = ; - */ - -// TODO: document each function -function listContacts() { - // ...your code -} - -function getContactById(contactId) { - // ...your code -} - -function removeContact(contactId) { - // ...your code -} - -function addContact(name, email, phone) { - // ...your code -} -``` - -## Step 3 - -Make an import of the `contacts.js` module in the `index.js` file and check the functionality of the functions for working with contacts. - -## Step 4 - -The `index.js` file imports the `yargs` package for convenient parsing of command line arguments. Use the ready-made function `invokeAction()` which receives the type of action to be performed and the required arguments. The function calls the appropriate method from the `contacts.js` file, passing it the necessary arguments. - -```js -// index.js -const argv = require('yargs').argv; - -// TODO: refactor -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -Alternatively, you can use the [commander](https://www.npmjs.com/package/commander) module to parse command line arguments. This is a more popular alternative to the `yargs` module. - -```js -const { Command } = require('commander'); -const program = new Command(); -program - .option('-a, --action ', 'choose action') - .option('-i, --id ', 'user id') - .option('-n, --name ', 'user name') - .option('-e, --email ', 'user email') - .option('-p, --phone ', 'user phone'); - -program.parse(process.argv); - -const argv = program.opts(); - -// TODO: refactor -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -## Step 5 - -Run the commands in the terminal and take a separate screenshot of the result of each command. - -```shell -# Get and display the entire list of contacts in the form of a table (console.table) -node index.js --action list - -# Get contact by id -node index.js --action get --id 05olLMgyVQdWRwgKfg5J6 - -# Add the contact -node index.js --action add --name Mango --email mango@gmail.com --phone 322-22-22 - -# Delete the contact -node index.js --action remove --id qdggE76Jtbfd9eWJHrssH -``` - -## Step 6 - Homework Submission - -Command execution screenshots can be uploaded to any free cloud image storage service (Example: [monosnap](https://monosnap.com/), [imgbb.com](https://imgbb.com/)) and the corresponding links are necessary add to the README.md file. Create this file at the root of the project. Then attach a link to the homework repository at [Schoology](https://app.schoology.com/login) for mentor to check. - -## Admission Criteria - -- You created a repository with homework — CLI application -- The assignment has been sent to the mentor at [Schoology](https://app.schoology.com/login) for review (repository link) -- The code corresponds to the terms of reference of the project -- No unhandled errors when executing code -- The names of variables, properties and methods start with a lowercase letter and are written in CamelCase notation. English nouns are used -- The name of the function or method contains a verb -- There are no commented sections of code in the code -- The project works correctly in the current LTS version of Node diff --git a/homework-01/README.es.md b/homework-01/README.es.md deleted file mode 100644 index a3f6957..0000000 --- a/homework-01/README.es.md +++ /dev/null @@ -1,164 +0,0 @@ -**Leer en otros idiomas: [Русский](README.md), [Українська](README.ua.md).** - -# Tarea 1 - -## Paso 1 - -- Inicia npm en el proyecto -- En la raíz del proyecto, cree un archivo `index.js` -- Pon el paquete [nodemon](https://www.npmjs.com/package/nodemon) como dependencia de desarrollo (devDependencies) -- En el archivo `package.json` añade "scripts" para iniciar `index.js` -- El script `start` que lanza `index.js` mediante `node` -- El script `start:dev` que lanza `index.js` mediante `nodemon` - -## Paso 2 - -En la raíz del proyecto cree una carpeta `db`. Descargue y utilice el archivo [contacts.json](./contacts.json) para almacenar los contactos, y colóquelo en la carpeta `db`. - -Cree un archivo `contacts.js` en la raíz del proyecto. - -- Importa los módulos `fs` y `path` para trabajar con el sistema de archivos. -- Cree una variable `contactsPath` y escribe en ella la ruta al archivo `contacts.json`. Utiliza los métodos del módulo `path` para elaborar la ruta. -- Añade funciones para trabajar con la colección de contactos. En las funciones, utiliza el módulo `fs` y sus métodos `readFile()` y `writeFile()`. -- Exporta las funciones creadas mediante `module.exports`. - -```js -// contacts.js - -/* - * Comenta y anota el valor - * const contactsPath = ; - */ - -// TODO: documenta cada función -function listContacts() { - // ...tu código -} - -function getContactById(contactId) { - // ...tu código -} - -function removeContact(contactId) { - // ...tu código -} - -function addContact(name, email, phone) { - // ...tu código -} -``` - -## Paso 3 - -Importa el módulo `contacts.js` en el archivo `index.js` y comprueba que las funciones para manipular los contactos funcionan. - -## Paso 4 - -En el archivo `index.js` se importa el paquete `yargs` para facilitar el análisis de los argumentos de la línea de comandos. Utilice la función ya preparada `invokeAction()` que obtiene el tipo de acción a realizar y los argumentos necesarios. La función llama al método apropiado del archivo `contacts.js` pasándole los argumentos necesarios. - -```js -// index.js -const argv = require('yargs').argv; - -// TODO: refactorizar -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -También puede utilizar el módulo [commander](https://www.npmjs.com/package/commander) para hacer parsing a los argumentos de la línea de comandos. Esta es una alternativa más popular al módulo `yargs'. - -```js -const { Command } = require('commander'); -const program = new Command(); -program - .option('-a, --action ', 'choose action') - .option('-i, --id ', 'user id') - .option('-n, --name ', 'user name') - .option('-e, --email ', 'user email') - .option('-p, --phone ', 'user phone'); - -program.parse(process.argv); - -const argv = program.opts(); - -// TODO: refactorizar -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -## Paso 5 - -Ejecuta los comandos en el terminal y haz una captura de pantalla del resultado de cada comando. - -```shell -# Obtenemos y mostramos la lista completa de contactos en forma de tabla (console.table). -node index.js --action list - -# Obtenemos un contacto según su id -node index.js --action get --id 05olLMgyVQdWRwgKfg5J6 - -# Añadimos un contacto -node index.js --action add --name Mango --email mango@gmail.com --phone 322-22-22 - -# Eliminamos un contacto -node index.js --action remove --id qdggE76Jtbfd9eWJHrssH -``` - -## Paso 6 - Entrega de la tarea. - -Las capturas de pantalla de la ejecución de los comandos, se pueden subir a cualquier servicio gratuito de almacenamiento de imágenes en la nube (Ejemplo: [monosnap](https://monosnap.com/), [imgbb.com](https://imgbb.com/)) y los enlaces pertinentes deben añadirse al archivo README.md. Cree este archivo en la raíz del proyecto. Después, adjunte un enlace al repositorio con la tarea a [schoology](https://app.schoology.com/login) para que el mentor la revise. - -## Requisitos para que sea admitida - -- Repositorio creado con la tarea — aplicación CLI -- Tarea enviada al mentor en [schoology](https://app.schoology.com/login) para su revisión (enlace al repositorio) -- El código se ajusta a la tarea técnica del proyecto -- No se producen errores sin procesar durante la ejecución del código -- Los nombres de variables, propiedades y métodos comienzan con una letra minúscula y se escriben en notación CamelCase. Se utilizan sustantivos en inglés -- El nombre de las funciones o métodos contiene un verbo -- No hay secciones de código comentadas en el código -- El proyecto funciona correctamente en la versión LTS actual de Node diff --git a/homework-01/README.md b/homework-01/README.md index c69e5ed..b67d049 100644 --- a/homework-01/README.md +++ b/homework-01/README.md @@ -1,165 +1,6 @@ -**Читать на других языках: [Русский](README.md), [Українська](README.ua.md).** +### Команди: -# Домашнее задание 1 - -## Шаг 1 - -- Инициализируй npm в проекте -- В корне проекта создай файл `index.js` -- Поставь пакет [nodemon](https://www.npmjs.com/package/nodemon) как зависимость разработки (devDependencies) -- В файле `package.json` добавь "скрипты" для запуска `index.js` -- Скрипт `start` который запускает `index.js` с помощью `node` -- Скрипт `start:dev` который запускает `index.js` с помощью `nodemon` - -## Шаг 2 - -В корне проекта создай папку `db`. Для хранения контактов скачай и используй файл [contacts.json](./contacts.json), положив его в папку `db`. - -В корне проекта создай файл `contacts.js`. - -- Сделай импорт модулей `fs` (в версии, которая работает с промисами - `fs/promises`) и `path` для работы с файловой системой -- Создай переменную `contactsPath` и запиши в нее путь к файле `contacts.json`. Для составления пути используй методы модуля `path`. -- Добавь функции для работы с коллекцией контактов. В функциях используй модуль `fs` и его методы `readFile()` и `writeFile()` -- Сделай экспорт созданных функций через `module.exports` - -```js -// contacts.js - -/* - * Раскомментируй и запиши значение - * const contactsPath = ; - */ - -// TODO: задокументировать каждую функцию -function listContacts() { - // ...твой код. Возвращает массив контактов. -} - -function getContactById(contactId) { - // ...твой код. Возвращает объект контакта с таким id. Возвращает null если объект с таким id не найден. -} - -function removeContact(contactId) { - // ...твой код. Возвращает объект удаленного контакта. Возвращает null если объект с таким id не найден. -} - -function addContact(name, email, phone) { - // ...твой код. Возвращает объект добавленного контакта. Возвращает null если объект с таким id не найден. -} -``` - -## Шаг 3 - -Сделай импорт модуля `contacts.js` в файле `index.js` и проверь работоспособность функций для работы с контактами. - -## Шаг 4 - -В файле `index.js` импортируется пакет `yargs` для удобного парса аргументов командной строки. Используй готовую функцию `invokeAction()` которая получает тип выполняемого действия и необходимые аргументы. Функция вызывает соответствующий метод из файла `contacts.js` передавая ему необходимые аргументы. - -```js -// index.js -const argv = require('yargs').argv; - -// TODO: рефакторить -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -Так же, вы можете использовать модуль [commander](https://www.npmjs.com/package/commander) для парсинга аргументов командной строки. Это более популярная альтернатива модуля `yargs` - -```js -const { Command } = require('commander'); -const program = new Command(); -program - .option('-a, --action ', 'choose action') - .option('-i, --id ', 'user id') - .option('-n, --name ', 'user name') - .option('-e, --email ', 'user email') - .option('-p, --phone ', 'user phone'); - -program.parse(process.argv); - -const argv = program.opts(); - -// TODO: рефакторить -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -## Шаг 5 - -Запусти команды в терминале и сделай отдельный скриншот результата выполнения каждой команды. - -```shell -# Получаем и выводим весь список контактов в виде таблицы (console.table) -node index.js --action list - -# Получаем контакт по id - выводим в консоль объект контакта или null если контакта с таким id не существует -node index.js --action get --id 05olLMgyVQdWRwgKfg5J6 - -# Добавляем контакт и выводим в консоль созданный контакт -node index.js --action add --name Mango --email mango@gmail.com --phone 322-22-22 - -# Удаляем контакт и выводим в консоль удаленный контакт или null если контакта с таким id не существует -node index.js --action remove --id qdggE76Jtbfd9eWJHrssH -``` - -## Шаг 6 - Сдача домашнего задания. - -Скриншоты выполнения команд, можно залить на любой бесплатный облачный сервис хранения картинок (Пример: [monosnap](https://monosnap.com/), [imgbb.com](https://imgbb.com/)) и соответствующие ссылки необходимо добавить в файл README.md. Создайте этот файл в корне проекта. После прикрепите ссылку на репозиторий с домашним заданием в [schoology](https://app.schoology.com/login) для проверки ментором. -Также в файл README.md нужно добавить ссылку на репозиторий со сделанной работой. - -## Критерии приема - -- Создан репозиторий с домашним заданием — CLI приложение -- Задание отправлено ментору в [schoology](https://app.schoology.com/login) на проверку (ссылка на репозиторий) -- Код соответствует техническому заданию проекта -- При выполнении кода не возникает необработанных ошибок -- Название переменных, свойств и методов начинается со строчной буквы и записываются в нотации CamelCase. Используются английские существительные -- Название функции или метода содержит глагол -- В коде нет закомментированных участков кода -- Проект корректно работает в актуальной LTS-версии Node +- `npm start` — старт сервера в режимі production +- `npm run start:dev` — старт сервера в режимі розробки (development) +- `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера +- `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок diff --git a/homework-01/README.pl.md b/homework-01/README.pl.md deleted file mode 100644 index 55e2c79..0000000 --- a/homework-01/README.pl.md +++ /dev/null @@ -1,164 +0,0 @@ -**Czytaj w innych językach: [rosyjski](README.md), [ukraiński](README.ua.md).** - -# Zadanie domowe 1 - -## Krok 1 - -- Zainicjalizuj npm w projekcie. -- W root projektu utwórz plik `index.js`. -- Ustaw pakiet [nodemon](https://www.npmjs.com/package/nodemon) jako zależność opracowywania (devDependencies). -- Do pliku `package.json` dodaj "skrytpy" dla włączenia `index.js`. -- Skrypt `start`, który uruchamia `index.js` przy pomocy `node`. -- Skrypt `start:dev`, który uruchamia `index.js` przy pomocy `nodemon`. - -## Krok 2 - -W root projektu utwórz plik `db`. Dla zapisywania kontaktów ściągnij i wykorzystaj plik [contacts.json](./contacts.json), umieszczając go w folderze `db`. - -W root projektu utwórz plik `contacts.js`. - -- Zaimportuj moduły `fs` i `path` do pracy z systemem plików. -- Utwórz zmienną `contactsPath` i zapisz w niej ścieżkę do pliku `contacts.json`. Do utworzenia ścieżki wykorzystaj metody modułu `path`. -- Dodaj funkcję do pracy ze zbiorem kontaktów. W funcjach wykorzystaj moduł `fs` oraz jego metody `readFile()` i `writeFile()`. -- Zrób eksport utworzonych funkcji przez `module.exports`. - -```js -// contacts.js - -/* - * Skomentuj i zapisz wartość - * const contactsPath = ; - */ - -// TODO: udokumentuj każdą funkcję -function listContacts() { - // ...twój kod -} - -function getContactById(contactId) { - // ...twój kod -} - -function removeContact(contactId) { - // ...twój kod -} - -function addContact(name, email, phone) { - // ...twój kod -} -``` - -## Krok 3 - -Utwórz import modułu `contacts.js` w pliku `index.js` i sprawdź wydajność funkcji dla pracy z kontaktami. - -## Krok 4 - -W pliku `index.js` importuje się pakiet `yargs` dla wygodnego parserowania argumentów wiersza poleceń. Wykorzystaj gotową funkcję `invokeAction()`, która otrzymuje typ wykonywanego działania i niezbędne argumenty. Funkcja wywołuje odpowiednią metodę z pliku `contacts.js`, przekazując mu niezbędne argumenty. - -```js -// index.js -const argv = require('yargs').argv; - -// TODO: refaktor -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -Możesz wykorzystać moduł [commander](https://www.npmjs.com/package/commander) do parserowania argumentów wiersza poleceń. To popularniejsza alternatywa modułu `yargs`. - -```js -const { Command } = require('commander'); -const program = new Command(); -program - .option('-a, --action ', 'choose action') - .option('-i, --id ', 'user id') - .option('-n, --name ', 'user name') - .option('-e, --email ', 'user email') - .option('-p, --phone ', 'user phone'); - -program.parse(process.argv); - -const argv = program.opts(); - -// TODO: refaktor -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -## Krok 5 - -Uruchom polecenia w terminalu i zrób oddzielne screenshoty wyników wykonania każdego polecenia. - -```shell -# Otrzymujemy i wyprowadzamy całą listę kontaktów w postaci tabeli (console.table) -node index.js --action list - -# Otrzymujemy kontakt po id -node index.js --action get --id 05olLMgyVQdWRwgKfg5J6 - -# Dodajemy kontakt -node index.js --action add --name Mango --email mango@gmail.com --phone 322-22-22 - -# Usuwamy kontakt -node index.js --action remove --id qdggE76Jtbfd9eWJHrssH -``` - -## Krok 6 - Oddanie pracy domowej - -Screenshoty wykonania poleceń można wysłać na dowolną, bezpłatną chmurę zapisywania obrazów (Przykład: [monosnap](https://monosnap.com/), [imgbb.com](https://imgbb.com/)) i odpowiednie odnośniki należy dodać do pliku README.md. Utwórz ten plik w root projektu. Następnie dodaj odnośnik do repozytorium z pracą domową do [schoology](https://app.schoology.com/login) dla sprawdzenia przez mentora. - -## Kryteria zaliczenia - -- Utworzone repozytorium z pracą domową — CLI aplikacja. -- Zadanie wysłane do mentora na [schoology](https://app.schoology.com/login) w celu sprawdzenia (odnośnik do repozytorium). -- Kod odpowiada technicznemu zadaniu projektu. -- W trakcie wykonywania kodu nie pojawiają się nieopracowane błędy. -- Nazwanie zmiennych, właściwości i metod zaczyna się z małej litery i zapisuje w notacji CamelCase. Wykorzystywane są angielskie rzeczowniki. -- Nazwa funkcji albo metoda zawiera czasownik. -- W kodzie nie ma skomentowanych fragmentów kodu. -- Projekt działa poprawnie w aktualnej wersji LTS Node. diff --git a/homework-01/README.ua.md b/homework-01/README.ua.md deleted file mode 100755 index 71d91b1..0000000 --- a/homework-01/README.ua.md +++ /dev/null @@ -1,165 +0,0 @@ -**Читати на інших мовах: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнє завдання 1 - -## Крок 1 - -- Ініціалізується npm в проекті -- В корені проекту створи файл `index.js` -- Постав пакет [nodemon](https://www.npmjs.com/package/nodemon) як залежність [nodemon](https://www.npmjs.com/package/nodemon) як залежність розробки (devDependencies) -- В файлі `package.json` додай "скрипти" для запуску `index.js` - - Скрипт `start` який запускає `index.js` за допомогою `node` - - Скрипт `dev` який запускає `index.js` за допомогою `nodemon` - -## Крок 2 - -У корені проекту створи папку `db`. Для зберігання контактів завантаж і використовуй файл [contacts.json](./contacts.json), поклавши його в папку `db`. - -У корені проекту створи файл `contacts.js`. - -- Зроби імпорт модулів `fs` (у версії, яка працює з промісами - `fs/promises`) і `path` для роботи з файловою системою -- Створи змінну `contactsPath` і запиши в неї шлях до файлі `contacts.json`. Для складання шляху використовуй методи модуля `path`. -- Додай функції для роботи з колекцією контактів. У функціях використовуй модуль `fs` та його методи `readFile()` і `writeFile()` -- Зроби експорт створених функцій через `module.exports` - -```js -// contacts.js - -/* - * Розкоментуйте і запишить значення - * const contactsPath = ; - */ - -// TODO: задокументувати кожну функцію -function listContacts() { - // ...твій код. Повертає масив контактів. -} - -function getContactById(contactId) { - // ...твій код. Повертає об'єкт контакту з таким id. Повертає null, якщо контакт з таким id не знайдений. -} - -function removeContact(contactId) { - // ...твій код. Повертає об'єкт видаленого контакту. Повертає null, якщо контакт з таким id не знайдений. -} - -function addContact(name, email, phone) { - // ...твій код. Повертає об'єкт доданого контакту. Повертає null, якщо контакт з таким id не знайдений. -} -``` - -## Крок 3 - -Зроби імпорт модуля `contacts.js` в файлі `index.js` та перевір працездатність функцій для роботи з контактами. - -## Крок 4 - -У файлі `index.js` імпортується пакет `yargs` для зручного парсу аргументів командного рядка. Використовуй готову функцію `invokeAction()` яка отримує тип виконуваної дії і необхідні аргументи. Функція викликає відповідний метод з файлу `contacts.js` передаючи йому необхідні аргументи. - -```js -// index.js -const argv = require('yargs').argv; - -// TODO: рефакторить -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -Так само, ви можете використовувати модуль [commander] (https://www.npmjs.com/package/commander) для парсинга аргументів командного рядка. Це більш популярна альтернатива модуля `yargs` - -```js -const { Command } = require('commander'); -const program = new Command(); -program - .option('-a, --action ', 'choose action') - .option('-i, --id ', 'user id') - .option('-n, --name ', 'user name') - .option('-e, --email ', 'user email') - .option('-p, --phone ', 'user phone'); - -program.parse(process.argv); - -const argv = program.opts(); - -// TODO: рефакторить -function invokeAction({ action, id, name, email, phone }) { - switch (action) { - case 'list': - // ... - break; - - case 'get': - // ... id - break; - - case 'add': - // ... name email phone - break; - - case 'remove': - // ... id - break; - - default: - console.warn('\x1B[31m Unknown action type!'); - } -} - -invokeAction(argv); -``` - -## Крок 5 - -Запусти команди в терміналі і зроби окремий скріншот результату виконання кожної команди. - -```shell -# Отримуємо і виводимо весь список контактів у вигляді таблиці (console.table) -node index.js --action="list" - -# Отримуємо контакт по id і виводимо у консоль об'єкт контакта або null якщо контакту з таким id не існує -node index.js --action="get" --id 05olLMgyVQdWRwgKfg5J6 - -# Додаємо контакт та виводимо в консоль об'єкт новоствореного контакту -node index.js --action="add" --name Mango --email mango@gmail.com --phone 322-22-22 - -# Видаляємо контакт та виводимо в консоль об'єкт видаленого контакту або null якщо контакту з таким id не існує -node index.js --action="remove" --id qdggE76Jtbfd9eWJHrssH -``` - -## Крок 6 - Здача домашнього завдання. - -Скріншоти виконання команд, можна залити на будь-який безкоштовний хмарний сервіс зберігання картинок (Приклад: [monosnap](https://monosnap.com/), [imgbb.com](https://imgbb.com/)) і відповідні посилання необхідно додати в файл README.md. Створіть цей файл в корені проекту. Після прикріпіть посилання на сховище з домашнім завданням в [schoology](https://app.schoology.com/login) для перевірки ментором. -Також у файл README.md треба додати посилання на репозиторій зі зробленою роботою. - -## Критерії прийому - -- Створено репозиторій з домашнім завданням — CLI додаток -- Завдання відправлено менторові в [schoology](https://app.schoology.com/login) на перевірку (посилання на репозиторій) -- Код відповідає технічному завданню проекту -- При виконанні коду не виникає необроблених помилок -- Назва змінних, властивостей і методів починається з малої літери і записуються в нотації CamelCase. Використовуються англійські іменники -- Назва функції або методу містить дієслово -- У коді немає закоментованих ділянок коду -- Проект коректно працює з актуальною LTS-версією Node diff --git a/homework-01/controllers/contacts.js b/homework-01/controllers/contacts.js new file mode 100644 index 0000000..72dbfeb --- /dev/null +++ b/homework-01/controllers/contacts.js @@ -0,0 +1,56 @@ +const { CtrlWrapper, HttpErrors } = require('../helpers/'); // Підключення модулів CtrlWrapper і HttpErrors з папки helpers +const contactsMethods = require('../models/contacts'); // Підключення модуля contactsMethods з папки models/contacts + +const getAll = async (req, res, next) => { + const list = await contactsMethods.listContacts(); // Виклик методу listContacts модуля contactsMethods для отримання списку контактів + res.json(list); // Відправка списку контактів у відповідь у форматі JSON +}; + +const getById = async (req, res, next) => { + const { contactId } = req.params; // Отримання значення параметра contactId з запиту + + const contact = await contactsMethods.getContactById(contactId); // Виклик методу getContactById модуля contactsMethods для отримання контакту за його ідентифікатором + + if (!contact) { + throw HttpErrors(404, 'Not found, man'); // Генерація об'єкта помилки HttpErrors зі статусом 404 та повідомленням "Not found, man" + } + + res.json(contact); // Відправка контакту у відповідь у форматі JSON +}; + +const addContact = async (req, res, next) => { + const newContact = await contactsMethods.addContact(req.body); // Виклик методу addContact модуля contactsMethods для додавання нового контакту з отриманими даними з тіла запиту + res.status(201).json(newContact); // Встановлення статусу відповіді 201 (Створено) та відправка створеного контакту у відповідь у форматі JSON +}; + +const deleteContact = async (req, res, next) => { + const { contactId } = req.params; // Отримання значення параметра contactId з запиту + + const delContact = await contactsMethods.removeContact(contactId); // Виклик методу removeContact модуля contactsMethods для видалення контакту за його ідентифікатором + + if (!delContact) { + throw HttpErrors(404, 'Not found'); // Генерація об'єкта помилки HttpErrors зі статусом 404 та повідомленням "Not found" + } + + res.json(delContact); // Відправка видаленого контакту у відповідь у форматі JSON +}; + +const updateContact = async (req, res, next) => { + const { contactId } = req.params; // Отримання значення параметра contactId з запиту + + const updContact = await contactsMethods.updateContact(contactId, req.body); // Виклик методу updateContact модуля contactsMethods для оновлення контакту за його ідентифікатором з отриманими даними з тіла запиту + + if (!updContact) { + throw HttpErrors(404, 'Not found'); // Генерація об'єкта помилки HttpErrors зі статусом 404 та повідомленням "Not found" + } + + res.json(updContact); // Відправка оновленого контакту у відповідь у форматі JSON +}; + +module.exports = { + getAll: CtrlWrapper(getAll), // Експорт методу getAll, обгорнутого в CtrlWrapper + getById: CtrlWrapper(getById), // Експорт методу getById, обгорнутого в CtrlWrapper + addContact: CtrlWrapper(addContact), // Експорт методу addContact, обгорнутого в CtrlWrapper + deleteContact: CtrlWrapper(deleteContact), // Експорт методу deleteContact, обгорнутого в CtrlWrapper + updateContact: CtrlWrapper(updateContact), // Експорт методу updateContact, обгорнутого в CtrlWrapper +}; diff --git a/homework-01/helpers/CtrlWrapper.js b/homework-01/helpers/CtrlWrapper.js new file mode 100644 index 0000000..8653b84 --- /dev/null +++ b/homework-01/helpers/CtrlWrapper.js @@ -0,0 +1,13 @@ +const CtrlWrapper = ctrl => { + const func = async (req, res, next) => { + try { + await ctrl(req, res, next); // Виклик контролера з переданими параметрами запиту, відповіді та наступної middleware + } catch (error) { + next(error); // Передача отриманої помилки до наступної middleware + } + }; + + return func; // Повернення обгортки контролера +}; + +module.exports = CtrlWrapper; // Експорт функції CtrlWrapper для використання в інших файлів diff --git a/homework-01/helpers/HttpErrors.js b/homework-01/helpers/HttpErrors.js new file mode 100644 index 0000000..22e5089 --- /dev/null +++ b/homework-01/helpers/HttpErrors.js @@ -0,0 +1,7 @@ +const HttpErrors = (status, message) => { + const error = new Error(message); // Створення нового об'єкта помилки з переданим повідомленням + error.status = status; // Присвоєння статусу помилки до властивості "status" об'єкта помилки + return error; // Повернення об'єкта помилки +}; + +module.exports = HttpErrors; // Експорт функції HttpErrors для використання в інших файлів diff --git a/homework-01/helpers/index.js b/homework-01/helpers/index.js new file mode 100644 index 0000000..0e791c1 --- /dev/null +++ b/homework-01/helpers/index.js @@ -0,0 +1,7 @@ +const HttpErrors = require('./HttpErrors.js'); // Підключення модуля HttpErrors з файлу HttpErrors.js +const CtrlWrapper = require('./CtrlWrapper.js'); // Підключення модуля CtrlWrapper з файлу CtrlWrapper.js + +module.exports = { + HttpErrors, // Експорт модуля HttpErrors для використання в інших файлах + CtrlWrapper, // Експорт модуля CtrlWrapper для використання в інших файлах +}; diff --git a/homework-01/middlewares/index.js b/homework-01/middlewares/index.js new file mode 100644 index 0000000..4771615 --- /dev/null +++ b/homework-01/middlewares/index.js @@ -0,0 +1,5 @@ +const validateBody = require('./validateBody'); // Підключення модуля validateBody для валідації запиту + +module.exports = { + validateBody, // Експорт функції validateBody для використання у інших файлів +}; diff --git a/homework-01/middlewares/validateBody.js b/homework-01/middlewares/validateBody.js new file mode 100644 index 0000000..4623201 --- /dev/null +++ b/homework-01/middlewares/validateBody.js @@ -0,0 +1,17 @@ +const { HttpErrors } = require('../helpers'); // Підключення модуля HttpErrors з папки helpers + +const validateBody = schema => { + const func = (req, res, next) => { + const { error } = schema.validate(req.body); // Валідація тіла запиту за допомогою заданої схеми + + if (error) { + next(HttpErrors(400, error.message)); // Якщо виникає помилка валідації, створюється об'єкт помилки HttpErrors зі статусом 400 та повідомленням про помилку + } + + next(); // Передача керування до наступної middleware + }; + + return func; // Повернення функції валідації +}; + +module.exports = validateBody; // Експорт функції validateBody для використання в інших файлів diff --git a/homework-01/models/contacts.js b/homework-01/models/contacts.js new file mode 100644 index 0000000..d420176 --- /dev/null +++ b/homework-01/models/contacts.js @@ -0,0 +1,82 @@ +const fs = require('fs/promises'); // Підключення модуля fs/promises для роботи з файловою системою (асинхронний підхід) +const path = require('path'); // Підключення модуля path для роботи зі шляхами файлів та каталогів +const { nanoid } = require('nanoid'); // Підключення функції nanoid з модуля nanoid для генерації унікальних ідентифікаторів + +const contactsPath = path.join(__dirname, 'contacts.json'); // Встановлення шляху до файлу contacts.json з використанням модуля path + +const listContacts = async () => { + // Функція для отримання списку контактів + const list = await fs.readFile(contactsPath, 'utf-8'); // Асинхронне читання файлу contacts.json + return JSON.parse(list); // Парсинг отриманого списку з формату JSON в об'єкт JavaScript +}; + +const getContactById = async contactId => { + // Функція для отримання контакту за його ідентифікатором + const list = await listContacts(); // Отримання списку контактів + + const contact = list.find(item => item.id === contactId); // Пошук контакту за його ідентифікатором + + return contact || null; // Повернення знайденого контакту або значення null, якщо контакт не знайдено +}; + +const addContact = async body => { + // Функція для додавання контакту + const list = await listContacts(); // Отримання списку контактів + + const newContact = { + // Створення нового контакту з унікальним ідентифікатором та даними з тіла запиту + id: nanoid(), + ...body, + }; + + list.push(newContact); // Додавання нового контакту до списку + + await fs.writeFile(contactsPath, JSON.stringify(list, null, 2)); // Асинхронне записування списку контактів у файл contacts.json + + return newContact; // Повернення доданого контакту +}; + +const removeContact = async contactId => { + // Функція для видалення контакту + const list = await listContacts(); // Отримання списку контактів + + const idx = list.findIndex(item => item.id === contactId); // Пошук індексу контакту за його ідентифікатором + + if (idx === -1) { + // Якщо контакт не знайдено + return null; // Повернення значення null + } + + const [contact] = list.splice(idx, 1); // Видалення контакту зі списку + + await fs.writeFile(contactsPath, JSON.stringify(list, null, 2)); // Асинхронне записування оновленого списку контактів у файл contacts.json + + return contact; // Повернення видаленого контакту +}; + +const updateContact = async (contactId, body) => { + // Функція для оновлення контакту + const list = await listContacts(); // Отримання списку контактів + + const idx = list.findIndex(item => item.id === contactId); // Пошук індексу контакту за його ідентифікатором + + if (idx === -1) { + // Якщо контакт не знайдено + return null; // Повернення значення null + } + + list[idx] = { id: contactId, ...body }; // Оновлення контакту з новими даними + + await fs.writeFile(contactsPath, JSON.stringify(list, null, 2)); // Асинхронне записування оновленого списку контактів у файл contacts.json + + return list[idx]; // Повернення оновленого контакту +}; + +module.exports = { + // Експорт функцій для використання у інших файлах + listContacts, + getContactById, + addContact, + removeContact, + updateContact, +}; diff --git a/homework-01/contacts.json b/homework-01/models/contacts.json similarity index 64% rename from homework-01/contacts.json rename to homework-01/models/contacts.json index a216791..14baea0 100644 --- a/homework-01/contacts.json +++ b/homework-01/models/contacts.json @@ -1,10 +1,4 @@ [ - { - "id": "AeHIrLTr6JkxGE6SN-0Rw", - "name": "Allen Raymond", - "email": "nulla.ante@vestibul.co.uk", - "phone": "(992) 914-3792" - }, { "id": "qdggE76Jtbfd9eWJHrssH", "name": "Chaim Lewis", @@ -58,5 +52,35 @@ "name": "Alec Howard", "email": "Donec.elementum@scelerisquescelerisquedui.net", "phone": "(748) 206-2688" + }, + { + "id": "Cs_BiasmIfd4SqctpF5UD", + "name": "You are", + "email": "the best", + "phone": "i proud of u" + }, + { + "id": "EOfu7wTP81qoer2WFgOBI", + "name": "You are, you are really nice", + "email": "the best developer", + "phone": "i proud of u, love" + }, + { + "id": "zQIUjBISdpgYXFLUjqAid", + "name": "Today is the best", + "email": "nice", + "phone": "day, i am happy" + }, + { + "id": "Yu8Qhjxdqs2H3Yl1ByBTD", + "name": "Today is the the the best best", + "email": "nice nice nice lovely", + "phone": "day, i am happy happy happy" + }, + { + "id": "qOX3O5kyiEAWansLQTJFM", + "name": "Today is the the the best best", + "email": "nice", + "phone": "day, i am happy happy happy" } -] +] \ No newline at end of file diff --git a/homework-01/nodemon.json b/homework-01/nodemon.json new file mode 100644 index 0000000..54d6947 --- /dev/null +++ b/homework-01/nodemon.json @@ -0,0 +1,3 @@ +{ + "ignore": ["node_modules", "models/contacts.json"] +} diff --git a/homework-01/routes/api/contacts.js b/homework-01/routes/api/contacts.js new file mode 100644 index 0000000..22a04df --- /dev/null +++ b/homework-01/routes/api/contacts.js @@ -0,0 +1,21 @@ +const express = require('express'); // Підключення модуля Express для створення роутера +const Joi = require('joi'); // Підключення модуля Joi для валідації даних +const ctrl = require('../../controllers/contacts'); // Підключення модуля контролера contacts +const { validateBody } = require('../../middlewares'); // Підключення мідлвари для валідації запиту + +const router = express.Router(); // Створення роутера за допомогою Express + +const addSchema = Joi.object({ + // Визначення схеми валідації для додавання контакту + name: Joi.string().required(), // Вимагається рядок з ім'ям + email: Joi.string().required(), // Вимагається рядок з електронною поштою + phone: Joi.string().required(), // Вимагається рядок з номером телефону +}); + +router.get('/', ctrl.getAll); // Роут для отримання всіх контактів +router.get('/:contactId', ctrl.getById); // Роут для отримання контакту за його ідентифікатором +router.post('/', validateBody(addSchema), ctrl.addContact); // Роут для додавання контакту з використанням мідлвари валідації +router.delete('/:contactId', validateBody(addSchema), ctrl.deleteContact); // Роут для видалення контакту з використанням мідлвари валідації +router.put('/:contactId', validateBody(addSchema), ctrl.updateContact); // Роут для оновлення контакту з використанням мідлвари валідації + +module.exports = router; // Експорт роутера для використання у інших файлів diff --git a/homework-01/server.js b/homework-01/server.js new file mode 100644 index 0000000..79e55cb --- /dev/null +++ b/homework-01/server.js @@ -0,0 +1,6 @@ +const app = require('./app'); // Підключення модуля `app` + +app.listen(3000, () => { + // Запуск сервера на порті 3000 + console.log('Server running. Use our API on port: 3000'); // Вивід повідомлення у консолі +}); From 472950a2e478ec10f4e78dfe4c382fff9018afb0 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Mon, 10 Jul 2023 18:54:41 +0300 Subject: [PATCH 2/9] homework --- homework-03/.env.example | 2 + homework-03/.eslintignore | 1 + homework-03/.eslintrc.js | 12 +++ homework-03/.gitignore | 4 + homework-03/README.en.md | 71 ---------------- homework-03/README.es.md | 71 ---------------- homework-03/README.md | 75 ++--------------- homework-03/README.pl.md | 72 ---------------- homework-03/README.ua.md | 77 ------------------ homework-03/atlas-cluster.jpg | Bin 119301 -> 0 bytes .../controllers/contacts-controller.js | 70 ++++++++++++++++ homework-03/helpers/HttpError.js | 15 ++++ homework-03/helpers/handleMongooseError.js | 8 ++ homework-03/helpers/index.js | 7 ++ homework-03/json-data.png | Bin 66986 -> 0 bytes homework-03/middlewares/index.js | 5 ++ homework-03/middlewares/isValidId.js | 14 ++++ homework-03/models/contacts.js | 31 +++++++ homework-03/{ => models}/contacts.json | 2 +- homework-03/models/index.js | 15 ++++ homework-03/mongo-data.png | Bin 38229 -> 0 bytes homework-03/nodemon.json | 3 + homework-03/routes/api/contacts.js | 41 ++++++++++ homework-03/schemas/contacts.js | 18 ++++ homework-03/schemas/index.js | 9 ++ homework-03/server.js | 15 ++++ homework-03/utils/ctrlWrapper.js | 13 +++ homework-03/utils/index.js | 7 ++ homework-03/utils/validateBody.js | 50 ++++++++++++ 29 files changed, 346 insertions(+), 362 deletions(-) create mode 100644 homework-03/.env.example create mode 100644 homework-03/.eslintignore create mode 100644 homework-03/.eslintrc.js create mode 100644 homework-03/.gitignore delete mode 100644 homework-03/README.en.md delete mode 100644 homework-03/README.es.md delete mode 100644 homework-03/README.pl.md delete mode 100755 homework-03/README.ua.md delete mode 100644 homework-03/atlas-cluster.jpg create mode 100644 homework-03/controllers/contacts-controller.js create mode 100644 homework-03/helpers/HttpError.js create mode 100644 homework-03/helpers/handleMongooseError.js create mode 100644 homework-03/helpers/index.js delete mode 100644 homework-03/json-data.png create mode 100644 homework-03/middlewares/index.js create mode 100644 homework-03/middlewares/isValidId.js create mode 100644 homework-03/models/contacts.js rename homework-03/{ => models}/contacts.json (99%) create mode 100644 homework-03/models/index.js delete mode 100644 homework-03/mongo-data.png create mode 100644 homework-03/nodemon.json create mode 100644 homework-03/routes/api/contacts.js create mode 100644 homework-03/schemas/contacts.js create mode 100644 homework-03/schemas/index.js create mode 100644 homework-03/server.js create mode 100644 homework-03/utils/ctrlWrapper.js create mode 100644 homework-03/utils/index.js create mode 100644 homework-03/utils/validateBody.js diff --git a/homework-03/.env.example b/homework-03/.env.example new file mode 100644 index 0000000..8115128 --- /dev/null +++ b/homework-03/.env.example @@ -0,0 +1,2 @@ +DB_HOST= +PORT= \ No newline at end of file diff --git a/homework-03/.eslintignore b/homework-03/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/homework-03/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/homework-03/.eslintrc.js b/homework-03/.eslintrc.js new file mode 100644 index 0000000..d799332 --- /dev/null +++ b/homework-03/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + env: { + commonjs: true, + es2021: true, + node: true, + }, + extends: ['standard', 'prettier'], + parserOptions: { + ecmaVersion: 12, + }, + rules: {}, +} diff --git a/homework-03/.gitignore b/homework-03/.gitignore new file mode 100644 index 0000000..8877fc5 --- /dev/null +++ b/homework-03/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.idea +.vscode \ No newline at end of file diff --git a/homework-03/README.en.md b/homework-03/README.en.md deleted file mode 100644 index 9963878..0000000 --- a/homework-03/README.en.md +++ /dev/null @@ -1,71 +0,0 @@ -**Read in other languages: [Russian](README.md), [Ukrainian](README.ua.md).** - -# Homework 3 - -Create branch `hw03-mongodb` from `master` branch. - -Continue building a REST API to work with the contact collection. - -## Step 1 - -Create an account on [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). Then create a new project in your account and set up a **free cluster**. When setting up the cluster, select the provider and region as in the screenshot below. If you select a region that is too remote, the server response time will be slower. - -![atlas cluster setup](./atlas-cluster.jpg) - -## Step 2 - -Install the graphical editor [MongoDB Compass](https://www.mongodb.com/products/compass) for convenient work with the database for MongoDB. Set up your cloud database connection to Compass. In MongoDB Atlas, don't forget to create an admin user. - -## Step 3 - -Through Compass, create the `db-contacts` database and the `contacts` collection in it. Take [link to json](./contacts.json) and use Compass to populate the `contacts` collection (make an import) with its contents. - -![data](./json-data.png) - -If you did everything right, the data should appear in your database in the `contacts` collection - -![data](./mongo-data.png) -## Step 4 - -Use the source code of [homework #2](../homework-02/README.md) and replace the contact storage from the json file with the database you created. - -- Write code to create a connection to MongoDB using [Mongoose](https://mongoosejs.com/). -- If the connection is successful, print the message `"Database connection successful"` to the console. -- Be sure to handle the connection error. Print an error message to the console and terminate the process using `process.exit(1)`. -- In the request processing functions, replace the code for CRUD operations on contacts from a file with Mongoose methods for working with a collection of contacts in the database. - -Model schema for the `contacts` collection: - -```js - { - name: { - type: String, - required: [true, 'Set name for contact'], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, - } -``` - -## Step 5 - -We have an additional status field `favorite` in contacts, which takes the boolean value `true` or `false`. It is responsible for the fact that the specified contact is in the favorites or not. Implement a new route to update contact status. - -### @ PATCH /api/contacts/:id/favorite - -- Gets the `contactId` parameter -- Gets `body` in JSON format with the update of the `favorite` field -- If there is no `body`, returns JSON with key `{"message": "missing field favorite"}` and status `400` -- If everything is fine with `body`, call the `updateStatusContact(contactId, body)` function (write it) to update the contact in the database -- Based on the result of the function, it returns an updated contact object with a status of `200`. Otherwise, returns JSON with `"message": "Not found"` key and `404` status - - -For the `POST /api/contacts` route, make changes: If the `favorite` field is not specified in `body`, then when saving a new contact to the database, make the `favorite` field equal to the default `false`. Don't forget about data validation! diff --git a/homework-03/README.es.md b/homework-03/README.es.md deleted file mode 100644 index 88c672f..0000000 --- a/homework-03/README.es.md +++ /dev/null @@ -1,71 +0,0 @@ -**Leer en otros idiomas: [Русский](README.md), [Українська](README.ua.md).** - -# Tarea 3 - -Crea una rama `hw03-mongodb` de la rama `master`. - -Continúa con la creación de la API REST para trabajar con una colección de contactos. - -## Paso 1 - -Crea una cuenta en [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). A continuación, cree un nuevo proyecto en su cuenta y configure un **clúster gratuito**. Cuando configure el clúster, seleccione su ISP y su región como se muestra en la captura de pantalla siguiente. Si elige una región demasiado alejada, la velocidad de respuesta del servidor será más lenta. - -![atlas cluster setup](./atlas-cluster.jpg) - -## Paso 2 - -Instala el redactor gráfico [MongoDB Compass](https://www.mongodb.com/products/compass) para un funcionamiento sencillo de la base de datos para MongoDB. Configure la conexión de su base de datos en la nube con Compass. En MongoDB Atlas, recuerda crear un usuario con privilegios de administrador. - -## Paso 3 - -Utilice Compass para crear una base de datos `db-contacts` y cree una colección `contacts` en ella. Usando el [link a json](./contacts.json) y utilizando Compass, llena la colección `contacts` (importándolo) con su contenido. - -![data](./json-data.png) - -Si lo has hecho correctamente, los datos deberían aparecer en tu base de datos en la colección `contacts`. - -![data](./mongo-data.png) -## Paso 4 - -Utiliza el código fuente [tarea #2](../homework-02/README.md) y sustituye el almacenamiento de contactos del archivo json, por la base de datos que has creado. - -- Escribe el código para crear una conexión a MongoDB usando [Mongoose](https://mongoosejs.com/). -- Si la conexión tiene éxito, muestra en la consola el mensaje `"Database connection successful"`. -- Asegúrese de atender el error de conexión. Muestra un mensaje de error en la consola y termina el proceso usando `process.exit(1)`. -- En las funciones de consulta, sustituya el código de las operaciones CRUD sobre contactos del archivo, por métodos de Mongoose para trabajar con una colección de contactos en la base de datos. - -Esquema del modelo de la colección `contacts`: - -```js - { - name: { - type: String, - required: [true, 'Set name for contact'], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, - } -``` - -## Paso 5 - -Tenemos un campo de estado adicional `favorite` en los contactos, que toma un valor booleano de `true` o `false`. Es responsable de que el contacto especificado esté o no en favoritos. Implementa una nueva ruta para actualizar el estado del contacto - -### @ PATCH /api/contacts/:id/favorite - -- Recibe el parámetro `contactId` -- Recibe `body` en formato json con el campo `favorito` actualizado -- Si no se encuentra `body`, devuelve un json con la llave `{"message": "missing field favorite"}` y el estado `400`. -- Si `body` está bien, llama a la función `updateStatusContact(contactId, body)` (escríbela) para actualizar el contacto en la base de datos -- La función devuelve un objeto de contacto actualizado con el estado `200`. En caso contrario, devuelve el json con la llave `"message": "Not found"` y el estado `404`. - - -Para el route `POST /api/contacts`, haz un cambio: si el campo `favorite` no se especifica en `body`, haz que el campo `favorite` sea por defecto `false` al guardar un nuevo contacto en la base de datos. No te olvides de la validación de los datos. diff --git a/homework-03/README.md b/homework-03/README.md index a4e86b2..b67d049 100644 --- a/homework-03/README.md +++ b/homework-03/README.md @@ -1,71 +1,6 @@ -**Читать на других языках: [Русский](README.md), [Українська](README.ua.md).** +### Команди: -# Домашнее задание 3 - -Создай ветку `hw03-mongodb` из ветки `master`. - -Продолжи создание REST API для работы с коллекцией контактов. - -## Шаг 1 - -Создай аккаунт на [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). После чего в аккаунте создай новый проект и настрой **бесплатный кластер**. Во время настройки кластера выбери провайдера и регион как на скриншоте ниже. Если выбрать слишком удаленный регион, скорость ответа сервера будет дольше. - -![atlas cluster setup](./atlas-cluster.jpg) - -## Шаг 2 - -Установи графический редактор [MongoDB Compass](https://www.mongodb.com/products/compass) для удобной работы с базой данных для MongoDB. Настрой подключение своей облачной базы данных к Compass. В MongoDB Atlas не забудь создать пользователя с правами администратора. - -## Шаг 3 - -Через Compass создай базу данных `db-contacts` и в ней коллекцию `contacts`. Возьми [ссылка на json](./contacts.json) и при помощи Compass наполни коллекцию `contacts` (сделай импорт) его содержимым. - -![data](./json-data.png) - -Если вы все сделали правильно, данные должны появиться в вашей базе в коллекции `contacts` - -![data](./mongo-data.png) -## Шаг 4 - -Используйте исходный код [домашней работы #2](../homework-02/README.md) и замените хранение контактов из json-файла на созданную вами базу данных. - -- Напишите код для создания подключения к MongoDB при помощи [Mongoose](https://mongoosejs.com/). -- При успешном подключении выведите в консоль сообщение `"Database connection successful"`. -- Обязательно обработайте ошибку подключения. Выведите в консоль сообщение ошибки и завершите процесс используя `process.exit(1)`. -- В функциях обработки запросов замените код CRUD-операций над контактами из файла, на Mongoose-методы для работы с коллекцией контактов в базе данных. - -Схема модели для коллекции `contacts`: - -```js - { - name: { - type: String, - required: [true, 'Set name for contact'], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, - } -``` - -## Шаг 5 - -У нас появилось в контактах дополнительное поле статуса `favorite`, которое принимает логическое значение `true` или `false`. Оно отвечает за то, что в избранном или нет находится указанный контакт. Реализуй для обновления статуса контакта новый маршрут - -### @ PATCH /api/contacts/:id/favorite - -- Получает параметр `contactId` -- Получает `body` в json-формате c обновлением поля `favorite` -- Если `body` нет, возвращает json с ключом `{"message": "missing field favorite"}` и статусом `400` -- Если с `body` все хорошо, вызывает функцию `updateStatusContact(contactId, body)` (напиши ее) для обновления контакта в базе -- По результату работы функции возвращает обновленный объект контакта и статусом `200`. В противном случае, возвращает json с ключом `"message": "Not found"` и статусом `404` - - -Для роута `POST /api/contacts` внесите изменения: если поле `favorite` не указали в `body`, то при сохранении в базу нового контакта, сделайте поле `favorite` равным по умолчанию `false`. Не забываем про валидацию данных! \ No newline at end of file +- `npm start` — старт сервера в режимі production +- `npm run start:dev` — старт сервера в режимі розробки (development) +- `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера +- `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок diff --git a/homework-03/README.pl.md b/homework-03/README.pl.md deleted file mode 100644 index ed79dd9..0000000 --- a/homework-03/README.pl.md +++ /dev/null @@ -1,72 +0,0 @@ -**Czytaj w innych językach: [rosyjski](README.md), [ukraiński](README.ua.md).** - -# Zadanie domowe 3 - -Utwórz gałąź `hw03-mongodb` z gałęzi `master`. - -Kontynuuj tworzenie REST API do pracy ze zbiorem kontaktów. - -## Krok 1 - -Stwórz konto na [MongoDB Atlas](https://www.mongodb.com/cloud/atlas), a następnie na koncie utwórz nowy projekt i skonfiguruj **bezpłatny klaster**. W czasie konfigurowania klastera wybierz provider i region, jak na screenshocie poniżej. Jeżeli wybierzesz zbyt oddalony region, serwer odpowie wolniej. - -![atlas cluster setup](./atlas-cluster.jpg) - -## Krok 2 - -Skonfiguruj edytor graficzny [MongoDB Compass](https://www.mongodb.com/products/compass) do wygodnej pracy z bazą danych dla MongoDB. Skonfiguruj podłączenie swojej chmury do Compass. W MongoDB Atlas nie zapomnij utworzyć użytkownika z prawami administratora. - -## Krok 3 - -Przez Compass utwórz bazę danych `db-contacts`, a w niej zbiór `contacts`. Weź [odnośnik do json](./contacts.json) i przy pomocy Compass wypełnij zbiór `contacts` (zaimportuj) jego zawartością. - -![data](./json-data.png) - -Jeżeli wszystko zrobiłeś prawidłowo, dane powinny się pojawić w twojej bazie w zbiorze `contacts` - -![data](./mongo-data.png). - -## Krok 4 - -Wykorzystaj kod źródłowy [zadania domowego #2](../homework-02/README.md) i zamień zapisywanie kontaktów z pliku json na utworzoną przez siebie bazę danych. - -- Napisz kod do utworzenia podłączenia do MongoDB przy pomocy [Mongoose](https://mongoosejs.com/). -- Przy sukcesie podłączenia wyprowadź na konsolę wiadomość `"Database connection successful"`. -- Obowiązkowo opracuj błąd podłączenia. Wyprowadź na konsolę wiadomość o błędzie i zakończ proces, wykorzystując `process.exit(1)`. -- W funkcjach opracowywania zapytań zamień kod operacji CRUD na kontaktach z pliku, na metody Mongoose do pracy ze zbiorem kontaktów w bazie danych. - -Schemat modeli dla zbioru `contacts`: - -```js - { - name: { - type: String, - required: [true, 'Set name for contact'], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, - } -``` - -## Krok 5 - -W naszych kontaktach pojawiło się dodatkowe pole statusu `favorite`, które przyjmuje logiczną wartość `true` lub `false`. Odpowiada ono za to, że wskazany kontakt znajduje się lub nie w ulubionych. Zrealizuj dla aktualizacji statusu kontaktu nową trasę. - -### @ PATCH /api/contacts/:id/favorite - -- Otrzymuje parametr `contactId`. -- Otrzymuje `body` w formacie json z aktualizacją pola `favorite`. -- Jeżeli `body` nie ma, zwraca json z kluczem `{"message": "missing field favorite"}` i statusem `400`. -- Jeżeli w `body` wszystko się zgadza to wywołaj funkcję `updateStatusContact(contactId, body)` (napisz ją), aby zaktualizować kontakt w bazie danych -- W wyniku pracy funkcji zwraca zaktualizowany obiekt kontaktu ze statusem `200`. W przeciwnym razie zwraca json z kluczem `"message": "Not found"` i statusem `404`. - - -Dla routa `POST /api/contacts` wprowadź zmiany: jeśli pole `favorite` nie zostało wskazane w `body`, to przy zapisaniu w bazie nowego kontaktu ustaw pole `favorite` domyślnie w `false`. Nie zapominajmy o walidacji danych! diff --git a/homework-03/README.ua.md b/homework-03/README.ua.md deleted file mode 100755 index 0791cc5..0000000 --- a/homework-03/README.ua.md +++ /dev/null @@ -1,77 +0,0 @@ -**Читати на інших мовах: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнє завдання 3 - -Створи гілку `03-mongodb` з гілки `master`. - -Продовж створення REST API для роботи з колекцією контактів. - -## Крок 1 - -Створи аккаунт на [MongoDB Atlas](https://www.mongodb.com/cloud/atlas). Після чого в акаунті створи новий проект і налаштуй **безкоштовний кластер**. Під час налаштування кластера вибери провавйдера і регіон як на скріншоті нижче. Якщо вибрати занадто віддалений регіон, швидкість відповіді сервера буде довше. - -![atlas cluster setup](./atlas-cluster.jpg) - -## Крок 2 - -Установи графічний редактор -[MongoDB Compass](https://www.mongodb.com/products/compass) для зручної -роботи з базою даних для MongoDB. Налаштуй підключення своєї хмарної бази даних -до Compass. У MongoDB Atlas не забудь створити користувача з правами -адміністратора. - -## Крок 3 - -Через Compass створи базу даних `db-contacts` і в ній колекцію `contacts`. Візьми [посилання на json](./contacts) і за допомогою Compass наповни колекцію `contacts` (зроби імпорт) його вмістом. - -![data](./json-data.png) - -Якщо ви все зробили правильно, дані повинні з'явитися у вашій базі в колекції `contacts` - -![data](./mongo-data.png) - -## Крок 4 - -Використовуй вихідний код [домашньої роботи #2](../homework-02/README.md) і -заміни зберігання контактів з json-файлу на створену тобою базу даних. - -- Напиши код для створення підключення до MongoDB за допомогою [Mongoose](https://mongoosejs.com/). -- При успішному підключенні виведи в консоль повідомлення `"Database connection successful"`. -- Обов'язково обробив помилку підключення. Виведи в консоль повідомлення помилки і заверши процес використовуючи `process.exit(1)`. -- У функціях обробки запитів заміни код CRUD-операцій над контактами з файлу, на Mongoose-методи для роботи з колекцією контактів в базі даних. - -Схема моделі для колекції `contacts`: - -```js - { - name: { - type: String, - required: [true, 'Set name for contact'], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, - } -``` - -## Крок 5 - -У нас з'явилося в контактах додаткове поле статусу `favorite`, яке приймає логічне значення` true` або `false`. Воно відповідає за те, що в обраному чи ні знаходиться зазначений контакт. Потрібно реалізувати для оновлення статусу контакту новий роутер - -### @ PATCH /api/contacts/:id/favorite - -- Отримує параметр `contactId` -- Отримує `body` в json-форматі з оновленням поля` favorite` -- Якщо `body` немає, повертає json з ключем` { "message": "missing field favorite"} `і статусом` 400` -- Якщо з `body` все добре, викликає функцію` updateStatusContact (contactId, body)` (напиши її) для поновлення контакту в базі) -- За результатом роботи функції повертає оновлений об'єкт контакту і статусом `200`. В іншому випадку, повертає json з ключем `" message ":" Not found "` і статусом `404` - - -Для роута `POST /api/contacts` внеси зміни: якщо поле `favorite` не вказали в `body`, то при збереженні в базу нового контакту, зроби поле `favorite` рівним за замовчуванням `false` \ No newline at end of file diff --git a/homework-03/atlas-cluster.jpg b/homework-03/atlas-cluster.jpg deleted file mode 100644 index 1002e724e4b7486c216e2bf9e1eda8a4e7ac4f94..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 119301 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 Fe*yI` { + const contacts = await Contacts.find(); + res.json(contacts); +}; + +const getContactById = async (req, res) => { + const contact = await Contacts.findById(req.params.contactId); + if (!contact) throw HttpError(404); + + res.status(200).json(contact); +}; + +const postContact = async (req, res) => { + const contact = await Contacts.create(req.body); + + res.status(201).json(contact); +}; + +const deleteContactByid = async (req, res) => { + const { contactId } = req.params; + const contact = await Contacts.findByIdAndDelete(contactId); + + if (!contact) throw HttpError(404, `contact with id ${contactId} not found`); + + res.json({ + message: "Contact deleted", + }); +}; + +const putContactById = async (req, res) => { + const { contactId } = req.params; + + const contact = await Contacts.findByIdAndUpdate(contactId, req.body, { + new: true, + }); + + if (!contact) { + throw HttpError(404); + } + + res.json(contact); +}; + +const updateStatusContact = async (req, res) => { + const { contactId } = req.params; + + const contact = await Contacts.findByIdAndUpdate(contactId, req.body, { + new: true, + }); + console.log("PATCH ", contact); + + if (!contact) { + throw HttpError(404); + } + + res.json(contact); +}; + +module.exports = { + getListContacts: ctrlWrapper(getListContacts), + getContactById: ctrlWrapper(getContactById), + postContact: ctrlWrapper(postContact), + deleteContactByid: ctrlWrapper(deleteContactByid), + putContactById: ctrlWrapper(putContactById), + updateStatusContact: ctrlWrapper(updateStatusContact), +}; diff --git a/homework-03/helpers/HttpError.js b/homework-03/helpers/HttpError.js new file mode 100644 index 0000000..3a04e07 --- /dev/null +++ b/homework-03/helpers/HttpError.js @@ -0,0 +1,15 @@ +const messages = { + 400: "Bad request", + 401: "Unauthorized", + 403: "Forbidden", + 404: "Not found", +}; + +const HttpError = (status, message = messages[status]) => { + const error = new Error(message); + error.status = status; + + return error; +}; + +module.exports = HttpError; diff --git a/homework-03/helpers/handleMongooseError.js b/homework-03/helpers/handleMongooseError.js new file mode 100644 index 0000000..920e4a4 --- /dev/null +++ b/homework-03/helpers/handleMongooseError.js @@ -0,0 +1,8 @@ +//alternative fast hand way to validate error +//for validation better to use joi and this method combined +const handleMongooseError = (error, data, next) => { + error.staus = 400; + next(); +}; + +module.exports = handleMongooseError; diff --git a/homework-03/helpers/index.js b/homework-03/helpers/index.js new file mode 100644 index 0000000..ee1386e --- /dev/null +++ b/homework-03/helpers/index.js @@ -0,0 +1,7 @@ +const HttpError = require("./HttpError"); +const handleMongooseError = require("./handleMongooseError"); + +module.exports = { + HttpError, + handleMongooseError, +}; diff --git a/homework-03/json-data.png b/homework-03/json-data.png deleted file mode 100644 index 904c47eec9fd19d4896c01316f6c66cf8108ed0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 66986 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 x*T`|0ks4=R+4EItD9&;~Yn;pOFT&!UGwb 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 { + const { contactId } = req.params; + + if (!isValidObjectId(contactId)) { + next(HttpError(400, `${contactId} is not valid id format`)); + } + + next(); +}; + +module.exports = isValidId; diff --git a/homework-03/models/contacts.js b/homework-03/models/contacts.js new file mode 100644 index 0000000..57011c6 --- /dev/null +++ b/homework-03/models/contacts.js @@ -0,0 +1,31 @@ +const fs = require("fs/promises"); +const path = require("path"); +const { nanoid } = require("nanoid"); +const { HttpError, handleMongooseError } = require("../helpers/index"); + +const contactsPath = path.resolve("models/contacts.json"); + +const { Schema, model } = require("mongoose"); + +const contactsSchema = new Schema({ + name: { + type: String, + required: [true, "Set name for contact"], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, +}); + +const Contacts = model("contacts", contactsSchema); + +contactsSchema.post("save", handleMongooseError); + +module.exports = Contacts; diff --git a/homework-03/contacts.json b/homework-03/models/contacts.json similarity index 99% rename from homework-03/contacts.json rename to homework-03/models/contacts.json index f2fa2e4..8a8e0e8 100644 --- a/homework-03/contacts.json +++ b/homework-03/models/contacts.json @@ -59,4 +59,4 @@ "phone": "(748) 206-2688", "favorite": true } -] +] \ No newline at end of file diff --git a/homework-03/models/index.js b/homework-03/models/index.js new file mode 100644 index 0000000..22d41da --- /dev/null +++ b/homework-03/models/index.js @@ -0,0 +1,15 @@ +const { + listContacts, + getContactById, + removeContact, + addContact, + updateContact, +} = require("../models/contacts.js"); + +module.exports = { + listContacts, + getContactById, + removeContact, + addContact, + updateContact, +}; diff --git a/homework-03/mongo-data.png b/homework-03/mongo-data.png deleted file mode 100644 index c46c4278305769174e600810b0d7940b4c1a7ed7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38229 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≷pD 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 { + app.listen(PORT, () => { + console.log("Server running. Use our API on port: 3000"); + }); + }) + .catch((error) => { + console.log(error); + process.exit(1); + }); diff --git a/homework-03/utils/ctrlWrapper.js b/homework-03/utils/ctrlWrapper.js new file mode 100644 index 0000000..fcd8365 --- /dev/null +++ b/homework-03/utils/ctrlWrapper.js @@ -0,0 +1,13 @@ +const ctrlWrapper = (method) => { + const func = async (req, res, next) => { + try { + await method(req, res, next); + } catch (error) { + next(error); + } + }; + + return func; +}; + +module.exports = ctrlWrapper; diff --git a/homework-03/utils/index.js b/homework-03/utils/index.js new file mode 100644 index 0000000..36f3f33 --- /dev/null +++ b/homework-03/utils/index.js @@ -0,0 +1,7 @@ +const ctrlWrapper = require('./ctrlWrapper'); +const validateBody = require('./validateBody'); + +module.exports = { + ctrlWrapper, + validateBody +}; \ No newline at end of file diff --git a/homework-03/utils/validateBody.js b/homework-03/utils/validateBody.js new file mode 100644 index 0000000..f4ee43b --- /dev/null +++ b/homework-03/utils/validateBody.js @@ -0,0 +1,50 @@ +const { HttpError } = require("../helpers"); + +const validateBody = (schema) => { + const func = (req, res, next) => { + const reqMethod = Object.keys(req.route.methods).join(""); + + if (reqMethod === "patch" && Object.keys(req.body).length === 0) + throw HttpError(400, "Missing field favorite"); + + if (Object.keys(req.body).length === 0) + throw HttpError(400, "Missing fields"); + + const { error } = schema.validate(req.body, { + abortEarly: false, + errors: { + wrap: { + label: false, + }, + }, + }); + + if (error && Object.keys(error._original).length === 3) { + let errArr = []; + + console.log("original schema error ", error._original); + for (let key in error._original) { + if (error._original[key].length === 0) errArr.push(key); + } + + throw HttpError( + 400, + `required ${errArr.join(", ")} not allowed to be empty` + ); + } + + if (error) { + console.log("validateBody schema error ", error); + throw HttpError( + 400, + `missing required ${error.message.replaceAll(".", ",")} field` + ); + } + + next(); + }; + + return func; +}; + +module.exports = validateBody; From b69fda681304772c1237da23e8876426705f2b00 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Mon, 10 Jul 2023 19:17:40 +0300 Subject: [PATCH 3/9] homework --- homework-03/.env.example | 2 - homework-03/.gitignore | 1 + .../controllers/contacts-controller.js | 70 ----------------- homework-03/controllers/contacts.js | 76 +++++++++++++++++++ homework-03/helpers/HttpError.js | 10 +-- homework-03/{utils => helpers}/ctrlWrapper.js | 4 +- homework-03/helpers/handleMongooseError.js | 4 +- homework-03/helpers/index.js | 6 +- homework-03/middlewares/index.js | 7 +- homework-03/middlewares/isValidId.js | 12 +-- homework-03/models/contact.js | 39 ++++++++++ homework-03/models/contacts.js | 31 -------- homework-03/models/contacts.json | 62 --------------- homework-03/models/index.js | 15 ---- homework-03/routes/api/contacts.js | 42 +++------- homework-03/schemas/contacts.js | 18 ----- homework-03/schemas/index.js | 9 --- homework-03/server.js | 19 ++--- homework-03/utils/index.js | 7 -- homework-03/utils/validateBody.js | 50 ------------ 20 files changed, 153 insertions(+), 331 deletions(-) delete mode 100644 homework-03/.env.example delete mode 100644 homework-03/controllers/contacts-controller.js create mode 100644 homework-03/controllers/contacts.js rename homework-03/{utils => helpers}/ctrlWrapper.js (68%) create mode 100644 homework-03/models/contact.js delete mode 100644 homework-03/models/contacts.js delete mode 100644 homework-03/models/contacts.json delete mode 100644 homework-03/models/index.js delete mode 100644 homework-03/schemas/contacts.js delete mode 100644 homework-03/schemas/index.js delete mode 100644 homework-03/utils/index.js delete mode 100644 homework-03/utils/validateBody.js diff --git a/homework-03/.env.example b/homework-03/.env.example deleted file mode 100644 index 8115128..0000000 --- a/homework-03/.env.example +++ /dev/null @@ -1,2 +0,0 @@ -DB_HOST= -PORT= \ No newline at end of file diff --git a/homework-03/.gitignore b/homework-03/.gitignore index 8877fc5..5c53556 100644 --- a/homework-03/.gitignore +++ b/homework-03/.gitignore @@ -1,4 +1,5 @@ node_modules/ .env +.env.local .idea .vscode \ No newline at end of file diff --git a/homework-03/controllers/contacts-controller.js b/homework-03/controllers/contacts-controller.js deleted file mode 100644 index 321fb02..0000000 --- a/homework-03/controllers/contacts-controller.js +++ /dev/null @@ -1,70 +0,0 @@ -const { HttpError } = require("../helpers/index.js"); -const { ctrlWrapper } = require("../utils/"); -const Contacts = require("../models/contacts.js"); - -const getListContacts = async (req, res) => { - const contacts = await Contacts.find(); - res.json(contacts); -}; - -const getContactById = async (req, res) => { - const contact = await Contacts.findById(req.params.contactId); - if (!contact) throw HttpError(404); - - res.status(200).json(contact); -}; - -const postContact = async (req, res) => { - const contact = await Contacts.create(req.body); - - res.status(201).json(contact); -}; - -const deleteContactByid = async (req, res) => { - const { contactId } = req.params; - const contact = await Contacts.findByIdAndDelete(contactId); - - if (!contact) throw HttpError(404, `contact with id ${contactId} not found`); - - res.json({ - message: "Contact deleted", - }); -}; - -const putContactById = async (req, res) => { - const { contactId } = req.params; - - const contact = await Contacts.findByIdAndUpdate(contactId, req.body, { - new: true, - }); - - if (!contact) { - throw HttpError(404); - } - - res.json(contact); -}; - -const updateStatusContact = async (req, res) => { - const { contactId } = req.params; - - const contact = await Contacts.findByIdAndUpdate(contactId, req.body, { - new: true, - }); - console.log("PATCH ", contact); - - if (!contact) { - throw HttpError(404); - } - - res.json(contact); -}; - -module.exports = { - getListContacts: ctrlWrapper(getListContacts), - getContactById: ctrlWrapper(getContactById), - postContact: ctrlWrapper(postContact), - deleteContactByid: ctrlWrapper(deleteContactByid), - putContactById: ctrlWrapper(putContactById), - updateStatusContact: ctrlWrapper(updateStatusContact), -}; diff --git a/homework-03/controllers/contacts.js b/homework-03/controllers/contacts.js new file mode 100644 index 0000000..edb8535 --- /dev/null +++ b/homework-03/controllers/contacts.js @@ -0,0 +1,76 @@ +const { Contact, addSchema, updateFavoriteSchema } = require('../models/contact'); + +const { HttpError } = require('../helpers'); +const ctrlWrapper = require('../helpers/ctrlWrapper'); + +const listContacts = async (req, res, next) => { + const result = await Contact.find(); + res.json(result); + console.log(result); +}; + +const getById = async (req, res, next) => { + const { id } = req.params; + const result = await Contact.findById(id); + if (!result) { + throw HttpError(404, 'Not found'); + } + res.json(result); +}; + +const addContact = async (req, res, next) => { + const { error } = addSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing required name field'); + } + const result = await Contact.create(req.body); + res.status(201).json(result); +}; + +const updateById = async (req, res, next) => { + const { error } = addSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing fields'); + } + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + if (!result) { + throw HttpError(404, 'Not found'); + } + res.json(result); +}; + +const updateStatusContact = async (req, res) => { + const { error } = updateFavoriteSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing field favorite'); + } + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + if (!result) { + throw HttpError(404, 'Not found'); + } + res.json(result); +}; + +const removeContact = async (req, res, next) => { + console.log(req.params); + const { id } = req.params; + const result = await Contact.findByIdAndDelete(id); + + if (!result) { + throw HttpError(404, 'Not found'); + } + res.json({ + message: 'contact deleted', + }); +}; + +module.exports = { + listContacts: ctrlWrapper(listContacts), + getById: ctrlWrapper(getById), + addContact: ctrlWrapper(addContact), + updateById: ctrlWrapper(updateById), + updateStatusContact: ctrlWrapper(updateStatusContact), + removeContact: ctrlWrapper(removeContact), +}; diff --git a/homework-03/helpers/HttpError.js b/homework-03/helpers/HttpError.js index 3a04e07..3f38b50 100644 --- a/homework-03/helpers/HttpError.js +++ b/homework-03/helpers/HttpError.js @@ -1,14 +1,6 @@ -const messages = { - 400: "Bad request", - 401: "Unauthorized", - 403: "Forbidden", - 404: "Not found", -}; - -const HttpError = (status, message = messages[status]) => { +const HttpError = (status, message) => { const error = new Error(message); error.status = status; - return error; }; diff --git a/homework-03/utils/ctrlWrapper.js b/homework-03/helpers/ctrlWrapper.js similarity index 68% rename from homework-03/utils/ctrlWrapper.js rename to homework-03/helpers/ctrlWrapper.js index fcd8365..4e36751 100644 --- a/homework-03/utils/ctrlWrapper.js +++ b/homework-03/helpers/ctrlWrapper.js @@ -1,7 +1,7 @@ -const ctrlWrapper = (method) => { +const ctrlWrapper = ctrl => { const func = async (req, res, next) => { try { - await method(req, res, next); + await ctrl(req, res, next); } catch (error) { next(error); } diff --git a/homework-03/helpers/handleMongooseError.js b/homework-03/helpers/handleMongooseError.js index 920e4a4..a3540bb 100644 --- a/homework-03/helpers/handleMongooseError.js +++ b/homework-03/helpers/handleMongooseError.js @@ -1,7 +1,5 @@ -//alternative fast hand way to validate error -//for validation better to use joi and this method combined const handleMongooseError = (error, data, next) => { - error.staus = 400; + error.status = 400; next(); }; diff --git a/homework-03/helpers/index.js b/homework-03/helpers/index.js index ee1386e..67fd13d 100644 --- a/homework-03/helpers/index.js +++ b/homework-03/helpers/index.js @@ -1,7 +1,9 @@ -const HttpError = require("./HttpError"); -const handleMongooseError = require("./handleMongooseError"); +const HttpError = require('./HttpError'); +const ctrl = require('./ctrlWrapper'); +const handleMongooseError = require('./handleMongooseError'); module.exports = { HttpError, + ctrl, handleMongooseError, }; diff --git a/homework-03/middlewares/index.js b/homework-03/middlewares/index.js index f985309..328e4eb 100644 --- a/homework-03/middlewares/index.js +++ b/homework-03/middlewares/index.js @@ -1,5 +1,2 @@ -const isValidId = require("./isValidId"); - -module.exports = { - isValidId, -}; +const isValidId = require('./isValidId'); +module.exports = isValidId; diff --git a/homework-03/middlewares/isValidId.js b/homework-03/middlewares/isValidId.js index 36725ee..41cd311 100644 --- a/homework-03/middlewares/isValidId.js +++ b/homework-03/middlewares/isValidId.js @@ -1,11 +1,11 @@ -const { isValidObjectId } = require("mongoose"); -const { HttpError } = require("../helpers"); +const { isValidObjectId } = require('mongoose'); -const isValidId = (req, res, next) => { - const { contactId } = req.params; +const { HttpError } = require('../helpers'); - if (!isValidObjectId(contactId)) { - next(HttpError(400, `${contactId} is not valid id format`)); +const isValidId = (req, res, next) => { + const { id } = req.params; + if (!isValidObjectId(id)) { + next(HttpError(400, `${id} is not valid id`)); } next(); diff --git a/homework-03/models/contact.js b/homework-03/models/contact.js new file mode 100644 index 0000000..a55c1c7 --- /dev/null +++ b/homework-03/models/contact.js @@ -0,0 +1,39 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const contactSchema = new Schema( + { + name: { + type: String, + required: [true, 'Set name for contact'], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, + }, + { versionKey: false }, +); + +contactSchema.post('save', handleMongooseError); + +const Contact = model('contact', contactSchema); + +const addSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().required(), + phone: Joi.string().required(), +}); + +const updateFavoriteSchema = Joi.object({ + favorite: Joi.boolean().required(), +}); + +module.exports = { Contact, addSchema, updateFavoriteSchema }; diff --git a/homework-03/models/contacts.js b/homework-03/models/contacts.js deleted file mode 100644 index 57011c6..0000000 --- a/homework-03/models/contacts.js +++ /dev/null @@ -1,31 +0,0 @@ -const fs = require("fs/promises"); -const path = require("path"); -const { nanoid } = require("nanoid"); -const { HttpError, handleMongooseError } = require("../helpers/index"); - -const contactsPath = path.resolve("models/contacts.json"); - -const { Schema, model } = require("mongoose"); - -const contactsSchema = new Schema({ - name: { - type: String, - required: [true, "Set name for contact"], - }, - email: { - type: String, - }, - phone: { - type: String, - }, - favorite: { - type: Boolean, - default: false, - }, -}); - -const Contacts = model("contacts", contactsSchema); - -contactsSchema.post("save", handleMongooseError); - -module.exports = Contacts; diff --git a/homework-03/models/contacts.json b/homework-03/models/contacts.json deleted file mode 100644 index 8a8e0e8..0000000 --- a/homework-03/models/contacts.json +++ /dev/null @@ -1,62 +0,0 @@ -[ - { - "name": "Allen Raymond", - "email": "nulla.ante@vestibul.co.uk", - "phone": "(992) 914-3792", - "favorite": false - }, - { - "name": "Chaim Lewis", - "email": "dui.in@egetlacus.ca", - "phone": "(294) 840-6685", - "favorite": true - }, - { - "name": "Kennedy Lane", - "email": "mattis.Cras@nonenimMauris.net", - "phone": "(542) 451-7038", - "favorite": false - }, - { - "name": "Wylie Pope", - "email": "est@utquamvel.net", - "phone": "(692) 802-2949", - "favorite": true - }, - { - "name": "Cyrus Jackson", - "email": "nibh@semsempererat.com", - "phone": "(501) 472-5218", - "favorite": true - }, - { - "name": "Abbot Franks", - "email": "scelerisque@magnis.org", - "phone": "(186) 568-3720", - "favorite": true - }, - { - "name": "Reuben Henry", - "email": "pharetra.ut@dictum.co.uk", - "phone": "(715) 598-5792", - "favorite": true - }, - { - "name": "Simon Morton", - "email": "dui.Fusce.diam@Donec.com", - "phone": "(233) 738-2360", - "favorite": true - }, - { - "name": "Thomas Lucas", - "email": "nec@Nulla.com", - "phone": "(704) 398-7993", - "favorite": false - }, - { - "name": "Alec Howard", - "email": "Donec.elementum@scelerisquescelerisquedui.net", - "phone": "(748) 206-2688", - "favorite": true - } -] \ No newline at end of file diff --git a/homework-03/models/index.js b/homework-03/models/index.js deleted file mode 100644 index 22d41da..0000000 --- a/homework-03/models/index.js +++ /dev/null @@ -1,15 +0,0 @@ -const { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -} = require("../models/contacts.js"); - -module.exports = { - listContacts, - getContactById, - removeContact, - addContact, - updateContact, -}; diff --git a/homework-03/routes/api/contacts.js b/homework-03/routes/api/contacts.js index 11bdebe..455a1cc 100644 --- a/homework-03/routes/api/contacts.js +++ b/homework-03/routes/api/contacts.js @@ -1,41 +1,21 @@ -const express = require("express"); -const { - getListContacts, - getContactById, - postContact, - deleteContactByid, - putContactById, - updateStatusContact, -} = require("../../controllers/contacts-controller.js"); -const { isValidId } = require("../../middlewares"); -const validateBody = require("../../utils/validateBody.js"); -const { - contactUpdateSchema, - contactUpdateFavoriteSchema, -} = require("../../schemas"); +const express = require('express'); const router = express.Router(); -router.get("/", getListContacts); +const ctrl = require('../../controllers/contacts'); -router.get("/:contactId", isValidId, getContactById); +const isValidId = require('../../middlewares'); -router.post("/", validateBody(contactUpdateSchema), postContact); +router.get('/', ctrl.listContacts); -router.delete("/:contactId", isValidId, deleteContactByid); +router.get('/:id', ctrl.getById); -router.put( - "/:contactId", - isValidId, - validateBody(contactUpdateSchema), - putContactById -); +router.post('/', ctrl.addContact); -router.patch( - "/:contactId/favorite", - isValidId, - validateBody(contactUpdateFavoriteSchema), - updateStatusContact -); +router.put('/:id', ctrl.updateById); + +router.patch('/:id/favorite', isValidId, ctrl.updateStatusContact); + +router.delete('/:id', ctrl.removeContact); module.exports = router; diff --git a/homework-03/schemas/contacts.js b/homework-03/schemas/contacts.js deleted file mode 100644 index ce710ed..0000000 --- a/homework-03/schemas/contacts.js +++ /dev/null @@ -1,18 +0,0 @@ -const Joi = require("joi"); - -const contactUpdateSchema = Joi.object({ - name: Joi.string().required().messages({'string.empty': '{#label}'}), - email: Joi.string().required().messages({'string.empty': '{#label}'}), - phone: Joi.string().required().messages({'string.empty': '{#label}'}), - favorite: Joi.boolean() -}) -.messages({'any.required': `{#label}`}) - -const contactUpdateFavoriteSchema = Joi.object({ - favorite: Joi.boolean().required() -}) - -module.exports = { - contactUpdateSchema, - contactUpdateFavoriteSchema -} \ No newline at end of file diff --git a/homework-03/schemas/index.js b/homework-03/schemas/index.js deleted file mode 100644 index e6b6c2c..0000000 --- a/homework-03/schemas/index.js +++ /dev/null @@ -1,9 +0,0 @@ -const { - contactUpdateSchema, - contactUpdateFavoriteSchema, -} = require("./contacts"); - -module.exports = { - contactUpdateSchema, - contactUpdateFavoriteSchema, -}; diff --git a/homework-03/server.js b/homework-03/server.js index 67faeaf..18f8256 100644 --- a/homework-03/server.js +++ b/homework-03/server.js @@ -1,15 +1,16 @@ -const app = require("./app"); -const mongoose = require("mongoose"); -const { DB_HOST, PORT } = process.env; +const mongoose = require('mongoose'); + +const app = require('./app'); + +const { DB_HOST, PORT = 3000 } = process.env; +// console.log(DB_HOST); mongoose .connect(DB_HOST) - .then((data) => { - app.listen(PORT, () => { - console.log("Server running. Use our API on port: 3000"); - }); + .then(() => { + app.listen(PORT); }) - .catch((error) => { - console.log(error); + .catch(error => { + console.log(error.message); process.exit(1); }); diff --git a/homework-03/utils/index.js b/homework-03/utils/index.js deleted file mode 100644 index 36f3f33..0000000 --- a/homework-03/utils/index.js +++ /dev/null @@ -1,7 +0,0 @@ -const ctrlWrapper = require('./ctrlWrapper'); -const validateBody = require('./validateBody'); - -module.exports = { - ctrlWrapper, - validateBody -}; \ No newline at end of file diff --git a/homework-03/utils/validateBody.js b/homework-03/utils/validateBody.js deleted file mode 100644 index f4ee43b..0000000 --- a/homework-03/utils/validateBody.js +++ /dev/null @@ -1,50 +0,0 @@ -const { HttpError } = require("../helpers"); - -const validateBody = (schema) => { - const func = (req, res, next) => { - const reqMethod = Object.keys(req.route.methods).join(""); - - if (reqMethod === "patch" && Object.keys(req.body).length === 0) - throw HttpError(400, "Missing field favorite"); - - if (Object.keys(req.body).length === 0) - throw HttpError(400, "Missing fields"); - - const { error } = schema.validate(req.body, { - abortEarly: false, - errors: { - wrap: { - label: false, - }, - }, - }); - - if (error && Object.keys(error._original).length === 3) { - let errArr = []; - - console.log("original schema error ", error._original); - for (let key in error._original) { - if (error._original[key].length === 0) errArr.push(key); - } - - throw HttpError( - 400, - `required ${errArr.join(", ")} not allowed to be empty` - ); - } - - if (error) { - console.log("validateBody schema error ", error); - throw HttpError( - 400, - `missing required ${error.message.replaceAll(".", ",")} field` - ); - } - - next(); - }; - - return func; -}; - -module.exports = validateBody; From 0aba386370c899ed4922c397b9a9291929bd3151 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Mon, 10 Jul 2023 19:36:30 +0300 Subject: [PATCH 4/9] homework --- homework-03/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/homework-03/README.md b/homework-03/README.md index b67d049..f3a8265 100644 --- a/homework-03/README.md +++ b/homework-03/README.md @@ -4,3 +4,4 @@ - `npm run start:dev` — старт сервера в режимі розробки (development) - `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера - `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок + From 59ffb3166d2e422ea6ebb67ca2e3f53b7b7ddfa6 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Mon, 10 Jul 2023 19:39:04 +0300 Subject: [PATCH 5/9] homework --- homework-03/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homework-03/README.md b/homework-03/README.md index f3a8265..0e4233d 100644 --- a/homework-03/README.md +++ b/homework-03/README.md @@ -4,4 +4,6 @@ - `npm run start:dev` — старт сервера в режимі розробки (development) - `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера - `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок +- `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок + From 756611bc1362a9b2060ca0b7912e54a13688ed25 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Thu, 13 Jul 2023 18:49:35 +0300 Subject: [PATCH 6/9] homework --- homework-04/.eslintignore | 1 + homework-04/.eslintrc.js | 12 + homework-04/.gitignore | 4 + homework-04/README.en.md | 255 ----------------- homework-04/README.es.md | 254 ----------------- homework-04/README.md | 258 +----------------- homework-04/README.pl.md | 253 ----------------- homework-04/README.ua.md | 251 ----------------- .../controllers/auth/changeSubscription.js | 13 + homework-04/controllers/auth/getCurrent.js | 11 + homework-04/controllers/auth/index.js | 13 + homework-04/controllers/auth/login.js | 41 +++ homework-04/controllers/auth/logout.js | 10 + homework-04/controllers/auth/register.js | 22 ++ .../controllers/contacts/addContact.js | 16 ++ homework-04/controllers/contacts/getById.js | 15 + homework-04/controllers/contacts/index.js | 15 + .../controllers/contacts/listContacts.js | 22 ++ .../controllers/contacts/removeContact.js | 17 ++ .../controllers/contacts/updateById.js | 21 ++ .../contacts/updateStatusContact.js | 21 ++ homework-04/helpers/HttpError.js | 7 + homework-04/helpers/ctrlWrapper.js | 13 + homework-04/helpers/handleMongooseError.js | 8 + homework-04/helpers/index.js | 9 + homework-04/middlewares/authenticate.js | 33 +++ homework-04/middlewares/index.js | 5 + homework-04/middlewares/isValidId.js | 15 + homework-04/middlewares/validateBody.js | 17 ++ homework-04/models/contact.js | 45 +++ homework-04/models/user.js | 69 +++++ homework-04/nodemon.json | 3 + homework-04/routes/api/auth.js | 22 ++ homework-04/routes/api/contacts.js | 23 ++ homework-04/server.js | 17 ++ 35 files changed, 545 insertions(+), 1266 deletions(-) create mode 100644 homework-04/.eslintignore create mode 100644 homework-04/.eslintrc.js create mode 100644 homework-04/.gitignore delete mode 100644 homework-04/README.en.md delete mode 100644 homework-04/README.es.md delete mode 100644 homework-04/README.pl.md delete mode 100755 homework-04/README.ua.md create mode 100644 homework-04/controllers/auth/changeSubscription.js create mode 100644 homework-04/controllers/auth/getCurrent.js create mode 100644 homework-04/controllers/auth/index.js create mode 100644 homework-04/controllers/auth/login.js create mode 100644 homework-04/controllers/auth/logout.js create mode 100644 homework-04/controllers/auth/register.js create mode 100644 homework-04/controllers/contacts/addContact.js create mode 100644 homework-04/controllers/contacts/getById.js create mode 100644 homework-04/controllers/contacts/index.js create mode 100644 homework-04/controllers/contacts/listContacts.js create mode 100644 homework-04/controllers/contacts/removeContact.js create mode 100644 homework-04/controllers/contacts/updateById.js create mode 100644 homework-04/controllers/contacts/updateStatusContact.js create mode 100644 homework-04/helpers/HttpError.js create mode 100644 homework-04/helpers/ctrlWrapper.js create mode 100644 homework-04/helpers/handleMongooseError.js create mode 100644 homework-04/helpers/index.js create mode 100644 homework-04/middlewares/authenticate.js create mode 100644 homework-04/middlewares/index.js create mode 100644 homework-04/middlewares/isValidId.js create mode 100644 homework-04/middlewares/validateBody.js create mode 100644 homework-04/models/contact.js create mode 100644 homework-04/models/user.js create mode 100644 homework-04/nodemon.json create mode 100644 homework-04/routes/api/auth.js create mode 100644 homework-04/routes/api/contacts.js create mode 100644 homework-04/server.js diff --git a/homework-04/.eslintignore b/homework-04/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/homework-04/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/homework-04/.eslintrc.js b/homework-04/.eslintrc.js new file mode 100644 index 0000000..d799332 --- /dev/null +++ b/homework-04/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + env: { + commonjs: true, + es2021: true, + node: true, + }, + extends: ['standard', 'prettier'], + parserOptions: { + ecmaVersion: 12, + }, + rules: {}, +} diff --git a/homework-04/.gitignore b/homework-04/.gitignore new file mode 100644 index 0000000..8877fc5 --- /dev/null +++ b/homework-04/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.idea +.vscode \ No newline at end of file diff --git a/homework-04/README.en.md b/homework-04/README.en.md deleted file mode 100644 index bf1a16a..0000000 --- a/homework-04/README.en.md +++ /dev/null @@ -1,255 +0,0 @@ -**Read in other languages: [Russian](README.md), [Ukrainian](README.ua.md).** - -# Homework 4 - -Create a `hw04-auth` branch from the `master` branch. - -Continue building a REST API to work with the contact collection. Add user authentication/authorization logic using [JWT](https://jwt.io/). - -## Step 1 - -In code, create a user schema and model for the `users` collection. - -```js -{ - password: { - type: String, - required: [true, 'Password is required'], - }, - email: { - type: String, - required: [true, 'Email is required'], - unique: true, - }, - subscription: { - type: String, - enum: ["starter", "pro", "business"], - default: "starter" - }, - token: { - type: String, - default: null, - }, -} -``` - -For each user to work and see only their contacts in the contact scheme, add the `owner` property. - -```js - owner: { - type: Schema.Types.ObjectId, - ref: 'user', - } -``` -Note: `'user'` is the name of the collection (singular) in which users are stored. - -## Step 2 - -### Registration - -Create an endpoint [`/users/signup`](#registration-request). - -Validate all required fields (`email` and `password`). Return on validation error -[Validation error](#registration-validation-error). - -In case of successful validation in the `User` model, create a user according to the data that has passed validation. For password salting use [bcrypt](https://www.npmjs.com/package/bcrypt) or [bcryptjs](https://www.npmjs.com/package/bcryptjs). - -- If the mail is already in use by someone else, return [Error Conflict](#registration-conflict-error). -- Otherwise return [Successful response](#registration-success-response). - -#### Registration Request - -```shell -POST /users/signup -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Registration Validation Error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Registration Conflict Error - -```shell -Status: 409 Conflict -Content-Type: application/json -ResponseBody: { - "message": "Email in use" -} -``` - -#### Registration Success Response - -```shell -Status: 201 Created -Content-Type: application/json -ResponseBody: { - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -### Login - -Create an endpoint [`/users/login`](#login-request) - -In the `User` model, find the user by `email`. - -Validate all required fields (`email` and `password`). If validation fails, return [Validation Error](#validation-error-login). - -- Otherwise, compare password for found user, if passwords match create token, store in current user and return a [Successful response](#login-success-response). - -- If password or email is incorrect, return [Error Unauthorized](#login-auth-error). - -#### Login request - -```shell -POST /users/login -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Login validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Login success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "token": "exampletoken", - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -#### Login auth error - -```shell -Status: 401 Unauthorized -ResponseBody: { - "message": "Email or password is wrong" -} -``` - -## Step 3 - -### Checking the token - -Create a middleware to validate the token and add it to all routes that need to be secured. - -- Middleware takes the token from the `Authorization` headers, checks the token for validity -- Return [Unauthorized Error](#middleware-unauthorized-error) on error -- If the validation was successful, get the user's `id` from the token. Find a user in the database by this id -- If the user exists and the token matches what is in the database, write his data to `req.user` and call the `next()` method -- If no user with that `id` exists or tokens don't match, return [Unauthorized Error](#middleware-unauthorized-error) - -#### Middleware unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -## Step 4 - -### Logout - -Create an endpoint [`/users/logout`](#logout-request) - -Add token verification middleware to the route. - -- In the `User` model, find the user by `_id` -- If the user does not exist, return [Error Unauthorized](#logout-unauthorized-error) -- Otherwise, delete the token in the current user and return [Successful response](#logout-success-response) - -#### Logout Request - -```shell -GET /users/logout -Authorization: "Bearer {{token}}" -``` - -#### Logout Unauthorized Error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Logout Success Response - -```shell -Status: 204 No Content -``` - -## Step 5 -### Current User - Get User Data by Token - -Create an endpoint [`/users/current`](#current-user-request) - -Add token verification middleware to the route. - -- If user does not have return [Error Unauthorized](#current-user-unauthorized-error) -- Otherwise, return [Successful response](#current-user-success-response) - -#### Current User Request - -```shell -GET /users/current -Authorization: "Bearer {{token}}" -``` - -#### Current User Unauthorized Error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Current User Success Response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "email": "example@example.com", - "subscription": "starter" -} -``` - -## Additional Task - Optional - -- Make pagination for the collection of contacts (GET /contacts?page=1&limit=20) -- Filter contacts by favorite field (GET /contacts?favorite=true) -- Updating a user's `subscription` via the `PATCH` `/users` endpoint. The subscription must have one of the following values `['starter', 'pro', 'business']` diff --git a/homework-04/README.es.md b/homework-04/README.es.md deleted file mode 100644 index 74ae915..0000000 --- a/homework-04/README.es.md +++ /dev/null @@ -1,254 +0,0 @@ -**Leer en otros idiomas: [Русский](README.md), [Українська](README.ua.md).** - -# Tarea 4 - -Crea una rama `hw04-auth` de la rama `master`. - -Continúe con la creación de una API REST para manejar la colección de contactos. Añadir la lógica de autenticación/autorización de usuarios mediante [JWT](https://jwt.io/). - -## Paso 1 - -En el código, crea un esquema y un modelo de usuario para la colección `users`. - -```js -{ - password: { - type: String, - required: [true, 'Password is required'], - }, - email: { - type: String, - required: [true, 'Email is required'], - unique: true, - }, - subscription: { - type: String, - enum: ["starter", "pro", "business"], - default: "starter" - }, - token: { - type: String, - default: null, - }, -} -``` - -Para que cada usuario funcione y vea sólo sus propios contactos en el esquema de contactos, añada la propiedad `owner`. - -```js - owner: { - type: Schema.Types.ObjectId, - ref: 'user', - } -``` -Nota: `'user'` es el nombre de la colección (única) en la que se almacenan los usuarios. - -## Paso 2 - -### Registro - -Crea el endpoint [`/users/signup`](#registration-request) - -Valida todos los campos obligatorios (`email` y `password`). Si se produce un error de validación, devuelve -[error de validación](#registration-validation-error). - -Si la validación es exitosa en el modelo `User`, crea un usuario basado en los datos validados. Para ponerle sal a las contraseñas, utilice [bcrypt](https://www.npmjs.com/package/bcrypt) o [bcryptjs](https://www.npmjs.com/package/bcryptjs) - -- Si el correo ya está en uso por otra persona, devuelve [Error Conflict](#registration-conflict-error). -- En caso contrario, devuelve [Respuesta exitosa](#registration-success-response). - -#### Registration request - -```shell -POST /users/signup -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Registration validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Registration conflict error - -```shell -Status: 409 Conflict -Content-Type: application/json -ResponseBody: { - "message": "Email in use" -} -``` - -#### Registration success response - -```shell -Status: 201 Created -Content-Type: application/json -ResponseBody: { - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -### Login - -Crea el endpoint [`/users/login`](#login-request) - -En el modelo `User`, busca el usuario por `email`. - -Valide todos los campos obligatorios (`email` y `password`). Si la validación falla, devuelve [Error de validación](#validation-error-login). - -- En caso contrario, compara la contraseña del usuario encontrado, si las contraseñas coinciden crea un token, guárdalo en el usuario actual y devuelve [Respuesta exitosa](#login-success-response). -- Si la contraseña o el correo electrónico son incorrectos, devuelve [Error Unauthorized](#login-auth-error). - -#### Login request - -```shell -POST /users/login -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Login validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Login success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "token": "exampletoken", - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -#### Login auth error - -```shell -Status: 401 Unauthorized -ResponseBody: { - "message": "Email or password is wrong" -} -``` - -## Paso 3 - -### Comprobación del token - -Crea un middleware para comprobar el token y añádelo a todas las rutas que deban ser protegidas. - -- El middleware toma el token de los encabezados de `Authorization`, comprueba la validez del token. -- En caso de error, devuelve [Error Unauthorized](#middleware-unauthorized-error). -- Si la validación es exitosa, recupera el `id` del usuario del token. Encuentra el usuario en la base de datos a partir de este ID. -- Si el usuario existe y el token coincide con el de la base de datos, escribe sus datos en `req.user` y llama al método `next()`. -- Si el usuario con este `id` no existe o los tokens no coinciden, devuelve [Error Unauthorized](#middleware-unauthorized-error) - -#### Middleware unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -## Paso 4 - -### Logout - -Crea el endpoint [`/users/logout`](#logout-request) - -Añade a la ruta el middleware para la comprobacióon de tokens. - -- En el modelo `User`, busca el usuario por `_id`. -- Si el usuario no existe, devuelve [Error Unauthorized](#logout-unauthorized-error). -- En caso contrario, elimina el token en el usuario actual y devuelve [Respuesta exitosa](#logout-success-response). - -#### Logout request - -```shell -GET /users/logout -Authorization: "Bearer {{token}}" -``` - -#### Logout unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Logout success response - -```shell -Status: 204 No Content -``` - -## Paso 5 -### Usuario actual. Recuperar los datos del usuario según el token - -Crea el endpoint [`/users/current`](#current-user-request) - -Añade a la ruta el middleware para la comprobacióon de tokens. - -- Si el usuario no existe, devuelve [Error Unauthorized](#current-user-unauthorized-error) -- EN caso contrario devuelve [Respuesta exitosa](#current-user-success-response) - -#### Current user request - -```shell -GET /users/current -Authorization: "Bearer {{token}}" -``` - -#### Current user unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Current user success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "email": "example@example.com", - "subscription": "starter" -} -``` - -## Tarea adicional (opcional) - -- Hacer una paginación de la colección de contactos (GET /contacts?page=1&limit=20). -- Filtra los contactos por favoritos (GET /contacts?favorite=true) -- Renovación de la suscripción (`subscription`) del usuario a travez del endpoint `PATCH` `/users`. La suscripción debe tener uno de los siguientes valores `['starter', 'pro', 'business']` diff --git a/homework-04/README.md b/homework-04/README.md index 3d908cf..b67d049 100644 --- a/homework-04/README.md +++ b/homework-04/README.md @@ -1,254 +1,6 @@ -**Читать на других языках: [Русский](README.md), [Українська](README.ua.md).** +### Команди: -# Домашнее задание 4 - -Создайте ветку `hw04-auth` из ветки `master`. - -Продолжите создание REST API для работы с коллекцией контактов. Добавьте логику аутентификации/авторизации пользователя с помощью [JWT](https://jwt.io/). - -## Шаг 1 - -В коде создайте схему и модель пользователя для коллекции `users`. - -```js -{ - password: { - type: String, - required: [true, 'Password is required'], - }, - email: { - type: String, - required: [true, 'Email is required'], - unique: true, - }, - subscription: { - type: String, - enum: ["starter", "pro", "business"], - default: "starter" - }, - token: { - type: String, - default: null, - }, -} -``` - -Чтобы каждый пользователь работал и видел только свои контакты в схеме контактов добавьте свойство `owner` - -```js - owner: { - type: Schema.Types.ObjectId, - ref: 'user', - } -``` -Примечание: `'user'` - название коллекции (в единственном числе), в которой хранятся пользователи. - -## Шаг 2 - -### Регистрация - -Создайте эндпоинт [`/users/signup`](#registration-request) - -Сделать валидацию всех обязательных полей (`email` и `password`). При ошибке валидации вернуть -[Ошибку валидации](#registration-validation-error). - -В случае успешной валидации в модели `User` создать пользователя по данным которые прошли валидацию. Для засолки паролей используй [bcrypt](https://www.npmjs.com/package/bcrypt) или [bcryptjs](https://www.npmjs.com/package/bcryptjs) - -- Если почта уже используется кем-то другим, вернуть [Ошибку Conflict](#registration-conflict-error). -- В противном случае вернуть [Успешный ответ](#registration-success-response). - -#### Registration request - -```shell -POST /users/signup -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Registration validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Ошибка от Joi или другой библиотеки валидации> -``` - -#### Registration conflict error - -```shell -Status: 409 Conflict -Content-Type: application/json -ResponseBody: { - "message": "Email in use" -} -``` - -#### Registration success response - -```shell -Status: 201 Created -Content-Type: application/json -ResponseBody: { - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -### Логин - -Создайте эндпоинт [`/users/login`](#login-request) - -В модели `User` найти пользователя по `email`. - -Сделать валидацию всех обязательных полей (`email` и `password`). При ошибке валидации вернуть [Ошибку валидации](#validation-error-login). - -- В противном случае, сравнить пароль для найденного юзера, если пароли совпадают создать токен, сохранить в текущем юзере и вернуть [Успешный ответ](#login-success-response). -- Если пароль или email неверный, вернуть [Ошибку Unauthorized](#login-auth-error). - -#### Login request - -```shell -POST /users/login -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Login validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Ошибка от Joi или другой библиотеки валидации> -``` - -#### Login success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "token": "exampletoken", - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -#### Login auth error - -```shell -Status: 401 Unauthorized -ResponseBody: { - "message": "Email or password is wrong" -} -``` - -## Шаг 3 - -### Проверка токена - -Создайте мидлвар для проверки токена и добавь его ко всем маршрутам, которые должны быть защищены. - -- Мидлвар берет токен из заголовков `Authorization`, проверяет токен на валидность. -- В случае ошибки вернуть [Ошибку Unauthorized](#middleware-unauthorized-error). -- Если валидация прошла успешно, получить из токена `id` пользователя. Найти пользователя в базе данных по этому id. -- Если пользователь существует и токен совпадает с тем, что находится в базе, записать его данные в `req.user` и вызвать метод`next()`. -- Если пользователя с таким `id` не существует или токены не совпадают, вернуть [Ошибку Unauthorized](#middleware-unauthorized-error) - -#### Middleware unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -## Шаг 4 - -### Логаут - -Создайте ендпоинт [`/users/logout`](#logout-request) - -Добавьте в маршрут мидлвар проверки токена. - -- В модели `User` найти пользователя по `_id`. -- Если пользователя не существует вернуть [Ошибку Unauthorized](#logout-unauthorized-error). -- В противном случае, удалить токен в текущем юзере и вернуть [Успешный ответ](#logout-success-response). - -#### Logout request - -```shell -GET /users/logout -Authorization: "Bearer {{token}}" -``` - -#### Logout unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Logout success response - -```shell -Status: 204 No Content -``` - -## Шаг 5 -### Текущий пользователь - получить данные юзера по токену - -Создайте эндпоинт [`/users/current`](#current-user-request) - -Добавьте в маршрут мидлвар проверки токена. - -- Если пользователя не существует вернуть [Ошибку Unauthorized](#current-user-unauthorized-error) -- В противном случае вернуть [Успешный ответ](#current-user-success-response) - -#### Current user request - -```shell -GET /users/current -Authorization: "Bearer {{token}}" -``` - -#### Current user unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Current user success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "email": "example@example.com", - "subscription": "starter" -} -``` - -## Дополнительное задание - необязательное - -- Сделать пагинацию для коллекции контактов (GET /contacts?page=1&limit=20). -- Сделать фильтрацию контактов по полю избранного (GET /contacts?favorite=true) -- Обновление подписки (`subscription`) пользователя через эндпоинт `PATCH` `/users`. Подписка должна иметь одно из следующих значений `['starter', 'pro', 'business']` +- `npm start` — старт сервера в режимі production +- `npm run start:dev` — старт сервера в режимі розробки (development) +- `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера +- `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок diff --git a/homework-04/README.pl.md b/homework-04/README.pl.md deleted file mode 100644 index 2008167..0000000 --- a/homework-04/README.pl.md +++ /dev/null @@ -1,253 +0,0 @@ -**Czytaj w innych językach: [rosyjski](README.md), [ukraiński](README.ua.md).** - -# Zadanie domowe 4 - -Utwórz gałąź `hw04-auth` z gałęzi `master`. - -Kontynuuj tworzenie REST API do pracy ze zbiorem kontaktów. Dodaj logikę uwierzytelnienia/autoryzacji użytkownika przy pomocy [JWT](https://jwt.io/). - -## Krok 1 - -Utwórz w kodzie schemat i model użytkownika dla zbioru `users`. - -```js -{ - password: { - type: String, - required: [true, 'Password is required'], - }, - email: { - type: String, - required: [true, 'Email is required'], - unique: true, - }, - subscription: { - type: String, - enum: ["starter", "pro", "business"], - default: "starter" - }, - token: { - type: String, - default: null, - }, -} -``` - -Aby każdy użytkownik działał i widział tylko swoje kontakty w schemacie kontaktów, dodaj właściwość `owner`. - -```js - owner: { - type: Schema.Types.ObjectId, - ref: 'user', - } -``` -Uwaga: `'user'` - nazwa zbioru (w liczbie pojedynczej), w którym zapisują się użytkownicy. - - -## Krok 2 - -### Rejestracja - -Utwórz endpoint [`/users/signup`](#registration-request). - -Zrób walidację wszystkich obowiązkowych pól (`email` i `password`). W przypadku błędu walidacji zwróć [Błąd walidacji](#registration-validation-error). - -W przypadku pomyślnej walidacji w modelu `User` utwórz użytkownika z danymi, które przeszły walidację. Dla wprowadzenia soli do haseł wykorzystaj [bcrypt](https://www.npmjs.com/package/bcrypt) lub [bcryptjs](https://www.npmjs.com/package/bcryptjs). - -- Jeśli poczta jest już wykorzystywana przez kogoś innego, zwróć [Błąd Conflict](#registration-conflict-error). -- W przeciwnym razie zwróć [Sukces odpowiedzi](#registration-success-response). - -#### Registration request - -```shell -POST /users/signup -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Registration validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Registration conflict error - -```shell -Status: 409 Conflict -Content-Type: application/json -ResponseBody: { - "message": "Email in use" -} -``` - -#### Registration success response - -```shell -Status: 201 Created -Content-Type: application/json -ResponseBody: { - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -### Login - -Utwórz endpoint [`/users/login`](#login-request). - -W modelu `User` znajdź użytkownika po `email`. - -Utwórz walidację wszystkich pól obowiązkowych (`email` i `password`). W przypadku błędu walidacji zwróć [Błąd walidacji](#validation-error-login). - -- W przeciwnym razie porównaj hasło dla znalezionego usera. Jeżeli hasła pokrywają się, utwórz token, zapisz w obecnym userze i zwróć [Sukces odpowiedzi](#login-success-response). -- Jeżeli hasło lub email nie są dokładne, zwróć [Błąd Unauthorized](#login-auth-error). - -#### Login request - -```shell -POST /users/login -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Login validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Login success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "token": "exampletoken", - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -#### Login auth error - -```shell -Status: 401 Unauthorized -ResponseBody: { - "message": "Email or password is wrong" -} -``` - -## Krok 3 - -### Sprawdzenie tokena - -Utwórz oprogramowanie pośredniczące tokena i dodaj je do wszystkich tras, które powinny być chronione. - -- Oprogramowanie pośredniczące bierze token z nagłówków `Authorization`, sprawdza token pod względem ważności. -- W przypadku błędu zwróć [Błąd Unauthorized](#middleware-unauthorized-error). -- Jeżeli walidacja przeszła pomyślnie, otrzymaj z tokena `id` użytkownika. Znajdź użytkownika w bazie danych po tym id. -- Jeśli użytkownik istnieje i token pokrywa się z tym, co znajduje się w bazie, zapisz jego dane w `req.user` i wywołaj metodę `next()`. -- Jeżeli użytkownika z takim `id` nie ma lub tokeny nie pokrywają się, zwróć [Błąd Unauthorized](#middleware-unauthorized-error). - -#### Middleware unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` -Krok 4 - -### Logout - -Utwórz endpoint [`/users/logout`](#logout-request). - -Dodaj do trasy program pośredniczący sprawdzania tokena. - -- W modelu `User` znajdź użytkownika po `_id`. -- Jeżeli nie można zwrócić użytkownika [Błąd Unauthorized](#logout-unauthorized-error). -- W przeciwnym razie usuń token w obecnym userze i zwróć [Sukces odpowiedzi](#logout-success-response). - -#### Logout request - -```shell -GET /users/logout -Authorization: "Bearer {{token}}" -``` - -#### Logout unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Logout success response - -```shell -Status: 204 No Content -``` - -## Krok 5 -### Obecny użytkownik – otrzymaj dane usera zgodnie z tokenem - -Utwórz endpoint [`/users/current`](#current-user-request). - -Dodaj do trasy program pośredniczący sprawdzania tokena. - -- Jeżeli użytkownik nie istnieje, zwróć [Błąd Unauthorized](#current-user-unauthorized-error). -- W przeciwnym razie zwróć [Sukces odpowiedzi](#current-user-success-response). - -#### Current user request - -```shell -GET /users/current -Authorization: "Bearer {{token}}" -``` - -#### Current user unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Current user success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "email": "example@example.com", - "subscription": "starter" -} -``` - -## Zadanie dodatkowe – nieobowiązkowe - -- Stwórz paginację dla zbioru kontaktów (GET /contacts?page=1&limit=20). -- Utwórz filtrowanie kontaktów zgodnie z polem wybranego (GET /contacts?favorite=true). -- Aktualizacja subskrypcji (`subscription`) użytkownika przez endpoint `PATCH` `/users`. Subskrypcja powinna mieć jedną z następujących wartości `['starter', 'pro', 'business']`. diff --git a/homework-04/README.ua.md b/homework-04/README.ua.md deleted file mode 100755 index 164fd71..0000000 --- a/homework-04/README.ua.md +++ /dev/null @@ -1,251 +0,0 @@ -**Читати на інших мовах: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнє завдання 4 - -Створи гілку `04-auth` з гілки `master`. - -Продовж створення REST API для роботи з колекцією контактів. Додай логіку аутентифікації/авторизації користувача через [JWT](https://jwt.io/). - -## Крок 1 - -У коді створи схему і модель користувача для колекції `users`. - -```js -{ - password: { - type: String, - required: [true, 'Set password for user'], - }, - email: { - type: String, - required: [true, 'Email is required'], - unique: true, - }, - subscription: { - type: String, - enum: ["starter", "pro", "business"], - default: "starter" - }, - token: String -} -``` - -Змініть схему контактів, щоб кожен користувач бачив тільки свої контакти. Для цього в схемі контактів додайте властивість - -```js - owner: { - type: Schema.Types.ObjectId, - ref: 'user', - } -``` -Примітка: `'user'` - назва колекції, у якій зберігаються користувачі - -## Крок 2 - -### Реєстрація - -Створити ендпоінт [`/users/register`](#registration-request) - -Зробити валідацію всіх обов'язкових полів (email і password). При помилці валідації повернути [Помилку валідації](#registration-validation-error). - -У разі успішної валідації в моделі `User` створити користувача за даними, які пройшли валідацію. Для засолювання паролів використовуй [bcrypt](https://www.npmjs.com/package/bcrypt) або [bcryptjs](https://www.npmjs.com/package/bcryptjs) - -- Якщо пошта вже використовується кимось іншим, повернути [Помилку Conflict](#registration-conflict-error). -- В іншому випадку повернути [Успішна відповідь](#registration-success-response). - -#### Registration request - -```shell -POST /users/register -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Registration validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Помилка від Joi або іншої бібліотеки валідації> -``` - -#### Registration conflict error - -```shell -Status: 409 Conflict -Content-Type: application/json -ResponseBody: { - "message": "Email in use" -} -``` - -#### Registration success response - -```shell -Status: 201 Created -Content-Type: application/json -ResponseBody: { - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -### Логін - -Створити ендпоінт [`/users/login`](#login-request) - -В моделі `User` знайти користувача за `email`. - -Зробити валідацію всіх обов'язкових полів (email і password). При помилці валідації повернути [Помилку валідації](#validation-error-login). - -- В іншому випадку, порівняти пароль для знайденого користувача, якщо паролі збігаються створити токен, зберегти в поточному юзера і повернути [Успішна відповідь](#login-success-response). -- Якщо пароль або імейл невірний, повернути [Помилку Unauthorized](#login-auth-error). - -#### Login request - -```shell -GET /users/login -Content-Type: application/json -RequestBody: { - "email": "example@example.com", - "password": "examplepassword" -} -``` - -#### Login validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Помилка від Joi або іншої бібліотеки валідації> -``` - -#### Login success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "token": "exampletoken", - "user": { - "email": "example@example.com", - "subscription": "starter" - } -} -``` - -#### Login auth error - -```shell -Status: 401 Unauthorized -ResponseBody: { - "message": "Email or password is wrong" -} -``` - -## Крок 3 - -### Перевірка токена - -Створи мідлвар для перевірки токена і додай його до всіх раутів, які повинні бути захищені. - -- Мідлвар бере токен з заголовків `Authorization`, перевіряє токен на валідність. -- У випадку помилки повернути [Помилку Unauthorized](#middleware-unauthorized-error). -- Якщо валідація пройшла успішно, отримати з токена `id` користувача. Знайти користувача в базі даних з цим `id`. -- Якщо користувач існує і токен збігається з тим, що знаходиться в базі, записати його дані в `req.user` і викликати `next()`. -- Якщо користувача з таким `id` НЕ існує або токени не збігаються, повернути [Помилку Unauthorized](#middleware-unauthorized-error) - -#### Middleware unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -## Крок 4 - -### Логаут - -Створити ендпоінт [`/users/logout`](#logout-request) - -Додай в маршрут мідлвар перевірки токена. - -- У моделі `User` знайти користувача за `_id`. -- Якщо користувача не існує повернути [Помилку Unauthorized](#logout-unauthorized-error). -- В іншому випадку, видалити токен у поточного юзера і повернути [Успішна відповідь](#logout-success-response). - -#### Logout request - -```shell -POST /users/logout -Authorization: "Bearer {{token}}" -``` - -#### Logout unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Logout success response - -```shell -Status: 204 No Content -``` - -## Крок 5 - -### Поточний користувач - отримати дані юзера по токену - -Створити ендпоінт [`/users/current`](#current-user-request) - -Додай в раут мідлвар перевірки токена. - -- Якщо користувача не існує повернути [Помилку Unauthorized](#current-user-unauthorized-error) -- В іншому випадку повернути [Успішну відповідь](#current-user-success-response) - -#### Current user request - -```shell -GET /users/current -Authorization: "Bearer {{token}}" -``` - -#### Current user unauthorized error - -```shell -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -#### Current user success response - -```shell -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "email": "example@example.com", - "subscription": "starter" -} -``` - -## Додаткове завдання - необов'язкове - -- Зробити пагінацію для колекції контактів (GET /contacts?page=1&limit=20). -- Зробити фільтрацію контактів по полю обраного (GET /contacts?favorite=true) -- Оновлення підписки (`subscription`) користувача через ендпоінт` PATCH` `/users`. Підписка повинна мати одне з наступних значень `['starter', 'pro', 'business']` diff --git a/homework-04/controllers/auth/changeSubscription.js b/homework-04/controllers/auth/changeSubscription.js new file mode 100644 index 0000000..1c11ed9 --- /dev/null +++ b/homework-04/controllers/auth/changeSubscription.js @@ -0,0 +1,13 @@ +const { User } = require('../../models/user'); + +const changeSubscription = async (req, res) => { + const { _id } = req.user; + const { subscription } = req.body; + await User.findByIdAndUpdate(_id, { subscription }); + + res.json({ + message: `Your subscription has been changed to ${subscription}`, + }); +}; + +module.exports = changeSubscription; diff --git a/homework-04/controllers/auth/getCurrent.js b/homework-04/controllers/auth/getCurrent.js new file mode 100644 index 0000000..8612179 --- /dev/null +++ b/homework-04/controllers/auth/getCurrent.js @@ -0,0 +1,11 @@ +const getCurrent = async (req, res) => { + const { name, email, subscription } = req.user; + + res.json({ + name, + email, + subscription, + }); +}; + +module.exports = getCurrent; diff --git a/homework-04/controllers/auth/index.js b/homework-04/controllers/auth/index.js new file mode 100644 index 0000000..20f103d --- /dev/null +++ b/homework-04/controllers/auth/index.js @@ -0,0 +1,13 @@ +const register = require('./register'); +const login = require('./login'); +const logout = require('./logout'); +const getCurrent = require('./getCurrent'); +const changeSubscription = require('./changeSubscription'); + +module.exports = { + register, + login, + logout, + getCurrent, + changeSubscription, +}; diff --git a/homework-04/controllers/auth/login.js b/homework-04/controllers/auth/login.js new file mode 100644 index 0000000..6d2a602 --- /dev/null +++ b/homework-04/controllers/auth/login.js @@ -0,0 +1,41 @@ +const bcryptjs = require('bcryptjs'); + +const jwt = require('jsonwebtoken'); + +const { User } = require('../../models/user'); + +const { HttpError } = require('../../helpers'); + +const { SECRET_KEY } = process.env; + +const login = async (req, res) => { + const { email, password } = req.body; + const user = await User.findOne({ email }); + + if (!user) { + throw HttpError(401, 'Email or password is wrong'); + } + + const passwordCompare = await bcryptjs.compare(password, user.password); + + if (!passwordCompare) { + throw HttpError(401, 'Email or password is wrong'); + } + + const payload = { + id: user._id, + }; + + const token = jwt.sign(payload, SECRET_KEY, { expiresIn: '7d' }); + await User.findByIdAndUpdate(user._id, { token }); + + res.json({ + token, + user: { + email: user.email, + subscription: user.subscription, + }, + }); +}; + +module.exports = login; diff --git a/homework-04/controllers/auth/logout.js b/homework-04/controllers/auth/logout.js new file mode 100644 index 0000000..c1505ae --- /dev/null +++ b/homework-04/controllers/auth/logout.js @@ -0,0 +1,10 @@ +const { User } = require('../../models/user'); + +const logout = async (req, res) => { + const { _id } = req.user; + await User.findByIdAndUpdate(_id, { token: '' }); + + res.status(204).json(); +}; + +module.exports = logout; diff --git a/homework-04/controllers/auth/register.js b/homework-04/controllers/auth/register.js new file mode 100644 index 0000000..5e46bdb --- /dev/null +++ b/homework-04/controllers/auth/register.js @@ -0,0 +1,22 @@ +const bcryptjs = require('bcryptjs'); +const { User } = require('../../models/user'); +const { HttpError } = require('../../helpers'); + +const register = async (req, res) => { + const { email, password } = req.body; + const user = await User.findOne({ email }); + + if (user) { + throw HttpError(409, 'Email in use'); + } + + const hashPassword = await bcryptjs.hash(password, 10); + const newUser = await User.create({ ...req.body, password: hashPassword }); + + res.status(201).json({ + name: newUser.name, + email: newUser.email, + }); +}; + +module.exports = register; diff --git a/homework-04/controllers/contacts/addContact.js b/homework-04/controllers/contacts/addContact.js new file mode 100644 index 0000000..2734a0b --- /dev/null +++ b/homework-04/controllers/contacts/addContact.js @@ -0,0 +1,16 @@ +const { Contact, addSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const addContact = async (req, res) => { + const { error } = addSchema.validate(req.body); + + if (error) { + throw HttpError(400, 'missing required name field'); + } + + const { _id: owner } = req.user; + const result = await Contact.create({ ...req.body, owner }); + res.status(201).json(result); +}; + +module.exports = addContact; diff --git a/homework-04/controllers/contacts/getById.js b/homework-04/controllers/contacts/getById.js new file mode 100644 index 0000000..c44471b --- /dev/null +++ b/homework-04/controllers/contacts/getById.js @@ -0,0 +1,15 @@ +const { Contact } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const getById = async (req, res) => { + const { id } = req.params; + const result = await Contact.findById(id); + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = getById; diff --git a/homework-04/controllers/contacts/index.js b/homework-04/controllers/contacts/index.js new file mode 100644 index 0000000..b4a4ed2 --- /dev/null +++ b/homework-04/controllers/contacts/index.js @@ -0,0 +1,15 @@ +const listContacts = require('./listContacts'); +const getById = require('./getById'); +const addContact = require('./addContact'); +const updateById = require('./updateById'); +const updateStatusContact = require('./updateStatusContact'); +const removeContact = require('./removeContact'); + +module.exports = { + listContacts, + getById, + addContact, + updateById, + updateStatusContact, + removeContact, +}; diff --git a/homework-04/controllers/contacts/listContacts.js b/homework-04/controllers/contacts/listContacts.js new file mode 100644 index 0000000..5f0b5e1 --- /dev/null +++ b/homework-04/controllers/contacts/listContacts.js @@ -0,0 +1,22 @@ +const { Contact } = require('../../models/contact'); + +const listContacts = async (req, res) => { + const { _id: owner } = req.user; + const { page = 1, limit = 10 } = req.query; + const skip = (page - 1) * limit; + + if (req.query.favorite) { + const favorite = req.query.favorite === 'true'; + const result = await Contact.find({ owner, favorite }, '', { + skip, + limit, + }).populate('owner', 'name email'); + + return res.json(result); + } + + const result = await Contact.find({ owner }, '', { skip, limit }).populate('owner', 'name email'); + res.json(result); +}; + +module.exports = listContacts; diff --git a/homework-04/controllers/contacts/removeContact.js b/homework-04/controllers/contacts/removeContact.js new file mode 100644 index 0000000..e0b2351 --- /dev/null +++ b/homework-04/controllers/contacts/removeContact.js @@ -0,0 +1,17 @@ +const { Contact } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const removeContact = async (req, res) => { + const { id } = req.params; + const result = await Contact.findByIdAndDelete(id); + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json({ + message: 'contact deleted', + }); +}; + +module.exports = removeContact; diff --git a/homework-04/controllers/contacts/updateById.js b/homework-04/controllers/contacts/updateById.js new file mode 100644 index 0000000..429b8cc --- /dev/null +++ b/homework-04/controllers/contacts/updateById.js @@ -0,0 +1,21 @@ +const { Contact, addSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const updateById = async (req, res) => { + const { error } = addSchema.validate(req.body); + + if (error) { + throw HttpError(400, 'missing fields'); + } + + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateById; diff --git a/homework-04/controllers/contacts/updateStatusContact.js b/homework-04/controllers/contacts/updateStatusContact.js new file mode 100644 index 0000000..ac5b428 --- /dev/null +++ b/homework-04/controllers/contacts/updateStatusContact.js @@ -0,0 +1,21 @@ +const { Contact, updateFavoriteSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const updateStatusContact = async (req, res) => { + const { error } = updateFavoriteSchema.validate(req.body); + + if (error) { + throw HttpError(400, 'missing field favorite'); + } + + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateStatusContact; diff --git a/homework-04/helpers/HttpError.js b/homework-04/helpers/HttpError.js new file mode 100644 index 0000000..3f38b50 --- /dev/null +++ b/homework-04/helpers/HttpError.js @@ -0,0 +1,7 @@ +const HttpError = (status, message) => { + const error = new Error(message); + error.status = status; + return error; +}; + +module.exports = HttpError; diff --git a/homework-04/helpers/ctrlWrapper.js b/homework-04/helpers/ctrlWrapper.js new file mode 100644 index 0000000..4e36751 --- /dev/null +++ b/homework-04/helpers/ctrlWrapper.js @@ -0,0 +1,13 @@ +const ctrlWrapper = ctrl => { + const func = async (req, res, next) => { + try { + await ctrl(req, res, next); + } catch (error) { + next(error); + } + }; + + return func; +}; + +module.exports = ctrlWrapper; diff --git a/homework-04/helpers/handleMongooseError.js b/homework-04/helpers/handleMongooseError.js new file mode 100644 index 0000000..f98813b --- /dev/null +++ b/homework-04/helpers/handleMongooseError.js @@ -0,0 +1,8 @@ +const handleMongooseError = (error, data, next) => { + const { name, code } = error; + const status = name === 'MongoServerError' && code === 11000 ? 409 : 400; + error.status = status; + next(); +}; + +module.exports = handleMongooseError; diff --git a/homework-04/helpers/index.js b/homework-04/helpers/index.js new file mode 100644 index 0000000..06f8c83 --- /dev/null +++ b/homework-04/helpers/index.js @@ -0,0 +1,9 @@ +const HttpError = require('./HttpError'); +const ctrlWrapper = require('./ctrlWrapper'); +const handleMongooseError = require('./handleMongooseError'); + +module.exports = { + HttpError, + ctrlWrapper, + handleMongooseError, +}; diff --git a/homework-04/middlewares/authenticate.js b/homework-04/middlewares/authenticate.js new file mode 100644 index 0000000..e79a9a9 --- /dev/null +++ b/homework-04/middlewares/authenticate.js @@ -0,0 +1,33 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models/user'); + +require('dotenv').config(); +const { SECRET_KEY } = process.env; + +const { HttpError } = require('../helpers'); + +const authenticate = async (req, res, next) => { + const { authorization = '' } = req.headers; + const [bearer, token] = authorization.split(' '); + + if (bearer !== 'Bearer') { + next(HttpError(401, 'Not authorized')); + } + + try { + const { id } = jwt.verify(token, SECRET_KEY); + const user = await User.findById(id); + + if (!user || !user.token || user.token !== token) { + next(HttpError(401, 'Not authorized')); + } + + req.user = user; + + next(); + } catch { + next(HttpError(401, 'Not authorized')); + } +}; + +module.exports = authenticate; diff --git a/homework-04/middlewares/index.js b/homework-04/middlewares/index.js new file mode 100644 index 0000000..4b9832e --- /dev/null +++ b/homework-04/middlewares/index.js @@ -0,0 +1,5 @@ +const isValidId = require('./isValidId'); +const authenticate = require('./authenticate'); +const validateBody = require('./validateBody'); + +module.exports = { isValidId, authenticate, validateBody }; diff --git a/homework-04/middlewares/isValidId.js b/homework-04/middlewares/isValidId.js new file mode 100644 index 0000000..3654e9a --- /dev/null +++ b/homework-04/middlewares/isValidId.js @@ -0,0 +1,15 @@ +const { isValidObjectId } = require('mongoose'); + +const { HttpError } = require('../helpers'); + +const isValidId = (req, res, next) => { + const { id } = req.params; + + if (!isValidObjectId(id)) { + next(HttpError(400, `${id} is not valid id`)); + } + + next(); +}; + +module.exports = isValidId; diff --git a/homework-04/middlewares/validateBody.js b/homework-04/middlewares/validateBody.js new file mode 100644 index 0000000..67ea2d5 --- /dev/null +++ b/homework-04/middlewares/validateBody.js @@ -0,0 +1,17 @@ +const { HttpError } = require('../helpers'); + +const validateBody = schema => { + const func = (req, res, next) => { + const { error } = schema.validate(req.body); + + if (error) { + next(HttpError(400, error.message)); + } + + next(); + }; + + return func; +}; + +module.exports = validateBody; diff --git a/homework-04/models/contact.js b/homework-04/models/contact.js new file mode 100644 index 0000000..c7a2729 --- /dev/null +++ b/homework-04/models/contact.js @@ -0,0 +1,45 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const contactSchema = new Schema( + { + name: { + type: String, + required: [true, 'Set name for contact'], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, + owner: { + type: Schema.Types.ObjectId, + ref: 'user', + required: true, + }, + }, + + { versionKey: false }, +); + +contactSchema.post('save', handleMongooseError); + +const Contact = model('contact', contactSchema); + +const addSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().required(), + phone: Joi.string().required(), +}); + +const updateFavoriteSchema = Joi.object({ + favorite: Joi.boolean().required(), +}); + +module.exports = { Contact, addSchema, updateFavoriteSchema }; diff --git a/homework-04/models/user.js b/homework-04/models/user.js new file mode 100644 index 0000000..719a2f3 --- /dev/null +++ b/homework-04/models/user.js @@ -0,0 +1,69 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const emailRegexp = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/; +const subscriptionList = ['starter', 'pro', 'business']; + +const userSchema = new Schema( + { + name: { + type: String, + required: true, + }, + email: { + type: String, + match: emailRegexp, + required: [true, 'Email is required'], + unique: true, + }, + password: { + type: String, + minlength: 6, + required: [true, 'Set password for user'], + }, + + subscription: { + type: String, + enum: subscriptionList, + default: 'starter', + }, + token: { + type: String, + default: '', + }, + }, + { versionKey: false }, +); + +userSchema.post('save', handleMongooseError); + +const registerSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().pattern(emailRegexp).required(), + password: Joi.string().min(6).required(), +}); + +const loginSchema = Joi.object({ + email: Joi.string().required(), + password: Joi.string().min(6).required(), +}); + +const changeSubscriptionSchema = Joi.object({ + subscription: Joi.string() + .valid(...subscriptionList) + .required(), +}); + +const User = model('user', userSchema); + +const schemas = { + registerSchema, + loginSchema, + changeSubscriptionSchema, +}; + +module.exports = { + User, + schemas, +}; diff --git a/homework-04/nodemon.json b/homework-04/nodemon.json new file mode 100644 index 0000000..54d6947 --- /dev/null +++ b/homework-04/nodemon.json @@ -0,0 +1,3 @@ +{ + "ignore": ["node_modules", "models/contacts.json"] +} diff --git a/homework-04/routes/api/auth.js b/homework-04/routes/api/auth.js new file mode 100644 index 0000000..cac67b8 --- /dev/null +++ b/homework-04/routes/api/auth.js @@ -0,0 +1,22 @@ +const express = require('express'); + +const { validateBody, authenticate } = require('../../middlewares'); +const { schemas } = require('../../models/user'); + +const router = express.Router(); + +const ctrl = require('../../controllers/auth'); + +const { ctrlWrapper } = require('../../helpers'); + +router.post('/register', validateBody(schemas.registerSchema), ctrlWrapper(ctrl.register)); + +router.post('/login', validateBody(schemas.loginSchema), ctrlWrapper(ctrl.login)); + +router.get('/current', authenticate, ctrlWrapper(ctrl.getCurrent)); + +router.post('/logout', authenticate, ctrlWrapper(ctrl.logout)); + +router.patch('/', authenticate, validateBody(schemas.changeSubscriptionSchema), ctrlWrapper(ctrl.changeSubscription)); + +module.exports = router; diff --git a/homework-04/routes/api/contacts.js b/homework-04/routes/api/contacts.js new file mode 100644 index 0000000..eeec574 --- /dev/null +++ b/homework-04/routes/api/contacts.js @@ -0,0 +1,23 @@ +const express = require('express'); + +const router = express.Router(); + +const ctrl = require('../../controllers/contacts'); + +const { ctrlWrapper } = require('../../helpers'); + +const { isValidId, authenticate } = require('../../middlewares'); + +router.get('/', authenticate, ctrlWrapper(ctrl.listContacts)); + +router.get('/:id', authenticate, isValidId, ctrlWrapper(ctrl.getById)); + +router.post('/', authenticate, ctrlWrapper(ctrl.addContact)); + +router.put('/:id', authenticate, isValidId, ctrlWrapper(ctrl.updateById)); + +router.patch('/:id/favorite', authenticate, isValidId, ctrlWrapper(ctrl.updateStatusContact)); + +router.delete('/:id', authenticate, isValidId, ctrlWrapper(ctrl.removeContact)); + +module.exports = router; diff --git a/homework-04/server.js b/homework-04/server.js new file mode 100644 index 0000000..2d1e335 --- /dev/null +++ b/homework-04/server.js @@ -0,0 +1,17 @@ +const mongoose = require('mongoose'); + +const app = require('./app'); +const { DB_HOST } = process.env; + +mongoose + .connect(DB_HOST) + .then(() => { + console.log('Database connection successful'); + app.listen(3000, () => { + console.log('Server running. Use our API on port: 3000'); + }); + }) + .catch(error => { + console.log(error.message); + process.exit(1); + }); From d1a980e33f98e6a52b7cc43756c462ccdc73b849 Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Fri, 21 Jul 2023 20:33:38 +0300 Subject: [PATCH 7/9] homework --- homework-05/.eslintignore | 1 + homework-05/.eslintrc.js | 12 +++ homework-05/.gitignore | 4 + homework-05/README.en.md | 84 ----------------- homework-05/README.es.md | 82 ----------------- homework-05/README.md | 86 +----------------- homework-05/README.pl.md | 82 ----------------- homework-05/README.ua.md | 80 ---------------- homework-05/avatar-upload.png | Bin 72253 -> 0 bytes .../controllers/auth/changeSubscription.js | 13 +++ homework-05/controllers/auth/getCurrent.js | 11 +++ homework-05/controllers/auth/index.js | 15 +++ homework-05/controllers/auth/login.js | 44 +++++++++ homework-05/controllers/auth/logout.js | 11 +++ homework-05/controllers/auth/register.js | 24 +++++ homework-05/controllers/auth/updateAvatar.js | 56 ++++++++++++ .../controllers/contacts/addContact.js | 15 +++ homework-05/controllers/contacts/getById.js | 14 +++ homework-05/controllers/contacts/index.js | 15 +++ .../controllers/contacts/listContacts.js | 26 ++++++ .../controllers/contacts/removeContact.js | 16 ++++ .../controllers/contacts/updateById.js | 20 ++++ .../contacts/updateStatusContact.js | 20 ++++ homework-05/helpers/HttpError.js | 7 ++ homework-05/helpers/ctrlWrapper.js | 14 +++ homework-05/helpers/handleMongooseError.js | 11 +++ homework-05/helpers/index.js | 11 +++ homework-05/helpers/resizeImage.js | 10 ++ homework-05/middlewares/authenticate.js | 34 +++++++ homework-05/middlewares/index.js | 5 + homework-05/middlewares/isValidId.js | 14 +++ homework-05/middlewares/upload.js | 19 ++++ homework-05/middlewares/validateBody.js | 17 ++++ homework-05/models/contact.js | 44 +++++++++ homework-05/models/user.js | 73 +++++++++++++++ homework-05/nodemon.json | 3 + homework-05/public/avatars/.gitkeep | 0 .../649c7f75733d3ba6bb281c92_avatar.jpg | Bin 0 -> 7676 bytes homework-05/routes/api/auth.js | 31 +++++++ homework-05/routes/api/contacts.js | 16 ++++ homework-05/server.js | 16 ++++ homework-05/temp/.gitkeep | 0 .../649c7f75733d3ba6bb281c92_avatar (2).jpg | Bin 0 -> 43425 bytes homework-05/temp/avatar.jpg | Bin 0 -> 43425 bytes 44 files changed, 647 insertions(+), 409 deletions(-) create mode 100644 homework-05/.eslintignore create mode 100644 homework-05/.eslintrc.js create mode 100644 homework-05/.gitignore delete mode 100644 homework-05/README.en.md delete mode 100644 homework-05/README.es.md delete mode 100644 homework-05/README.pl.md delete mode 100755 homework-05/README.ua.md delete mode 100644 homework-05/avatar-upload.png create mode 100644 homework-05/controllers/auth/changeSubscription.js create mode 100644 homework-05/controllers/auth/getCurrent.js create mode 100644 homework-05/controllers/auth/index.js create mode 100644 homework-05/controllers/auth/login.js create mode 100644 homework-05/controllers/auth/logout.js create mode 100644 homework-05/controllers/auth/register.js create mode 100644 homework-05/controllers/auth/updateAvatar.js create mode 100644 homework-05/controllers/contacts/addContact.js create mode 100644 homework-05/controllers/contacts/getById.js create mode 100644 homework-05/controllers/contacts/index.js create mode 100644 homework-05/controllers/contacts/listContacts.js create mode 100644 homework-05/controllers/contacts/removeContact.js create mode 100644 homework-05/controllers/contacts/updateById.js create mode 100644 homework-05/controllers/contacts/updateStatusContact.js create mode 100644 homework-05/helpers/HttpError.js create mode 100644 homework-05/helpers/ctrlWrapper.js create mode 100644 homework-05/helpers/handleMongooseError.js create mode 100644 homework-05/helpers/index.js create mode 100644 homework-05/helpers/resizeImage.js create mode 100644 homework-05/middlewares/authenticate.js create mode 100644 homework-05/middlewares/index.js create mode 100644 homework-05/middlewares/isValidId.js create mode 100644 homework-05/middlewares/upload.js create mode 100644 homework-05/middlewares/validateBody.js create mode 100644 homework-05/models/contact.js create mode 100644 homework-05/models/user.js create mode 100644 homework-05/nodemon.json create mode 100644 homework-05/public/avatars/.gitkeep create mode 100644 homework-05/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg create mode 100644 homework-05/routes/api/auth.js create mode 100644 homework-05/routes/api/contacts.js create mode 100644 homework-05/server.js create mode 100644 homework-05/temp/.gitkeep create mode 100644 homework-05/temp/649c7f75733d3ba6bb281c92_avatar (2).jpg create mode 100644 homework-05/temp/avatar.jpg diff --git a/homework-05/.eslintignore b/homework-05/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/homework-05/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/homework-05/.eslintrc.js b/homework-05/.eslintrc.js new file mode 100644 index 0000000..d799332 --- /dev/null +++ b/homework-05/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + env: { + commonjs: true, + es2021: true, + node: true, + }, + extends: ['standard', 'prettier'], + parserOptions: { + ecmaVersion: 12, + }, + rules: {}, +} diff --git a/homework-05/.gitignore b/homework-05/.gitignore new file mode 100644 index 0000000..8877fc5 --- /dev/null +++ b/homework-05/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.idea +.vscode \ No newline at end of file diff --git a/homework-05/README.en.md b/homework-05/README.en.md deleted file mode 100644 index 40df6c6..0000000 --- a/homework-05/README.en.md +++ /dev/null @@ -1,84 +0,0 @@ -**Read in other languages: [Russian](README.md), [Ukrainian](README.ua.md).** - -# Homework 5 - -Create the `hw05-avatars` branch from the `master` branch. - -Continue building a REST API to work with the contact collection. Add the ability to upload the user's avatar via [Multer](https://github.com/expressjs/multer). - -## Step 1 - -Create a folder `public` for distribution of statics. In this folder make a folder `avatars`. Set up Express to serve static files from the `public` folder. - -Put any image in the `public/avatars` folder and check that the static distribution works. When you navigate to such a URL, the browser will display the image. - -```shell -http://localhost:/avatars/ -``` - -## Step 2 - -Add a new `avatarURL` property to the user schema to hold the image. - -```shell -{ - ... - avatarURL: String, - ... -} -``` - -- Use the package [gravatar](https://www.npmjs.com/package/gravatar) to immediately generate an avatar for him by his `email` when registering a new user. - -## Step 3 - -When registering a user: - -- Create a link to the user's avatar with [gravatar](https://www.npmjs.com/package/gravatar) -- Save the resulting URL in the `avatarURL` field during user creation - -## Step 4 - -Add the ability to update the avatar by creating an endpoint `/users/avatars` and using the `PATCH` method. - -![avatar upload from postman](./avatar-upload.png) - -```shell -# Request -PATCH /users/avatars -Content-Type: multipart/form-data -Authorization: "Bearer {{token}}" -RequestBody: uploaded file - -# Successful response -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "avatarURL": "image link goes here" -} - -# Unsuccessful response -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -- Create a tmp folder in the root of the project and save the uploaded avatar to it -- Process the avatar with the [jimp] package (https://www.npmjs.com/package/jimp) and set its dimensions to 250 by 250 -- Move the user's avatar from the tmp folder to the `public/avatars` folder and give it a unique name for the specific user -- The resulting `URL` is `/avatars/`, save it in the user's `avatarURL` field - - -## Additional Task - Optional - -### 1. Write Unit Tests for the Login Controler (login/signin) - -Using [Jest](https://jestjs.io/ru/docs/getting-started) - -- Response must have status code 200 -- The token must be returned in the response -- The response should return a `user` object with 2 fields `email` and `subscription`, having the data type `String` - - diff --git a/homework-05/README.es.md b/homework-05/README.es.md deleted file mode 100644 index 0525dfc..0000000 --- a/homework-05/README.es.md +++ /dev/null @@ -1,82 +0,0 @@ -**Leer en otros idiomas: [Русский](README.md), [Українська](README.ua.md).** - -# Tarea 5 - -Crea una rama `hw05-avatars` de la rama `master`. - -Continúe construyendo la API REST para su colección de contactos. Añade la posibilidad de subir el avatar de usuario a través de [Multer](https://github.com/expressjs/multer). - -## Paso 1 - -Crea una carpeta `public` para la distribución de los archivos estáticos. Crea una carpeta llamada `avatars` en esta carpeta. Configura Express para que distribuya los archivos estáticos de la carpeta `public`. - -Coloca cualquier imagen en la carpeta `public/avatars` y asegúrate de que la distribución de archivos estáticos funciona. Al ir a esta URL, el navegador mostrará la imagen. - -```shell -http://localhost:/avatars/ -``` - -## Paso 2 - -Añade una nueva propiedad `avatarURL` al esquema de usuario para almacenar la imagen. - -```shell -{ - ... - avatarURL: String, - ... -} -``` - -- Utilice el paquete [gravatar](https://www.npmjs.com/package/gravatar) para generar inmediatamente un avatar cuando se registra un nuevo usuario, basandose en el `email` del usuario. - -## Paso 3 - -Al registrarse un usuario: - -- Crea un enlace al avatar del usuario utilizando [gravatar](https://www.npmjs.com/package/gravatar) -- Durante la creación del usuario, guarda la URL resultante en el campo `avatarURL` durante la creación del usuario - -## Paso 4 - -Añade la posibilidad de actualizar tu avatar creando un endpoint `/users/avatars` y utilizando el método `PATCH`. - -![avatar upload from postman](./avatar-upload.png) - -```shell -# Petición -PATCH /users/avatars -Content-Type: multipart/form-data -Authorization: "Bearer {{token}}" -RequestBody: archivo cargado - -# Respuesta exitosa -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "avatarURL": "aquí habrá un enlace a la imagen" -} - -# Respuesta fallida -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -- Crea una carpeta tmp en la raíz del proyecto y guarda en ella el avatar subido. -- Procesa el avatar con el paquete [jimp](https://www.npmjs.com/package/jimp) y asignales una dimensión de 250 por 250 -- Mueve el avatar del usuario de la carpeta tmp a la carpeta `public/avatars` y dale un nombre único para el usuario específico. -- Guardar la `URL` recuperada `/avatars/` en el campo `avatarURL` del usuario - -## Tarea adicional (opcional) - -### 1. Escribir pruebas unitarias para el controlador de entrada (login/signin) - -Usando [Jest](https://jestjs.io/ru/docs/getting-started) - -- la respuesta debe tener un código de estado de 200 -- la respuesta debe devolver un token -- La respuesta debe devolver un objeto `user` con 2 campos `email` y `subscription` de tipo de datos `String` - diff --git a/homework-05/README.md b/homework-05/README.md index daa90e3..b67d049 100644 --- a/homework-05/README.md +++ b/homework-05/README.md @@ -1,82 +1,6 @@ -**Читать на других языках: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнее задание 5 - -Создай ветку `hw05-avatars` из ветки `master`. - -Продолжи создание REST API для работы с коллекцией контактов. Добавь возможность загрузки аватарки пользователя через [Multer](https://github.com/expressjs/multer). - -## Шаг 1 - -Создай папку `public` для раздачи статики. В этой папке сделай папку `avatars`. Настрой Express на раздачу статических файлов из папки `public`. - -Положи любое изображение в папку `public/avatars` и проверь что раздача статики работает. При переходе по такому URL браузер отобразит изображение. - -```shell -http://localhost:<порт>/avatars/<имя файла с расширением> -``` - -## Шаг 2 - -В схему пользователя добавь новое свойство `avatarURL` для хранения изображения. - -```shell -{ - ... - avatarURL: String, - ... -} -``` - -- Используй пакет [gravatar](https://www.npmjs.com/package/gravatar) для того чтобы при регистрации нового пользователя сразу сгенерить ему аватар по его `email`. - -## Шаг 3 - -При регистрации пользователя: - -- Создавай ссылку на аватарку пользователя с помощью [gravatar](https://www.npmjs.com/package/gravatar) -- Полученный URL сохрани в поле `avatarURL` во время создания пользователя - -## Шаг 4 - -Добавь возможность обновления аватарки, создав эндпоинт `/users/avatars` и используя метод `PATCH`. - -![avatar upload from postman](./avatar-upload.png) - -```shell -# Запрос -PATCH /users/avatars -Content-Type: multipart/form-data -Authorization: "Bearer {{token}}" -RequestBody: загруженный файл - -# Успешный ответ -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "avatarURL": "тут будет ссылка на изображение" -} - -# Неуспешный ответ -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -- Создай папку tmp в корне проекта и сохраняй в неё загруженную аватарку. -- Обработай аватарку пакетом [jimp](https://www.npmjs.com/package/jimp) и задай для нее размеры 250 на 250 -- Перенеси аватарку пользователя из папки tmp в папку `public/avatars` и дай ей уникальное имя для конкретного пользователя. -- Полученный `URL` `/avatars/<имя файла с расширением>` сохрани в поле `avatarURL` пользователя - -## Дополнительное задание - необязательное - -### 1. Написать unit-тесты для контроллера входа (login/signin) - -При помощи [Jest](https://jestjs.io/ru/docs/getting-started) - -- ответ должен иметь статус-код 200 -- в ответе должен возвращаться токен -- в ответе должен возвращаться объект `user` с 2 полями `email` и `subscription`, имеющие тип данных `String` +### Команди: +- `npm start` — старт сервера в режимі production +- `npm run start:dev` — старт сервера в режимі розробки (development) +- `npm run lint` — запустити виконання перевірки коду з eslint, необхідно виконувати перед кожним PR та виправляти всі помилки лінтера +- `npm lint:fix` — та ж перевірка лінтера, але з автоматичними виправленнями простих помилок diff --git a/homework-05/README.pl.md b/homework-05/README.pl.md deleted file mode 100644 index 3ec1b6b..0000000 --- a/homework-05/README.pl.md +++ /dev/null @@ -1,82 +0,0 @@ -**Czytaj w innych językach: [rosyjski](README.md), [ukraiński](README.ua.md).** - -# Zadanie domowe 5 - -Utwórz gałąź `hw05-avatars` z gałęzi `master`. - -Kontynuuj tworzenie REST API do pracy ze zbiorem kontaktów. Dodaj opcję ładowania awataru użytkownika przez [Multer](https://github.com/expressjs/multer). - -## Krok 1 - -Stwórz folder `public` do rozdawania statyki. W tym folderze utwórz folder `avatars`. Narzędzie Express do rozdawania plików statycznych z folderu `public`. - -Umieść dowolny obraz w folderze `public/avatars` i sprawdź, czy rozdawanie statyki działa. Po przejściu po takim URL przeglądarka wyświetli obraz. - -```shell -http://localhost:<порт>/avatars/ -``` - -## Krok 2 - -Do schematu użytkownika dodaj nową właściwość `avatarURL` dla przechowywania obrazu. - -```shell -{ - ... - avatarURL: String, - ... -} -``` - -Wykorzystaj pakiet [gravatar](https://www.npmjs.com/package/gravatar), aby przy rejestracji nowego użytkownika od razu wygenerować mu awatar po jego `email`. - -## Krok 3 - -Przy rejestracji użytkownika: - -- Utwórz odnośnik do awatara użytkownika przy pomocy [gravatar](https://www.npmjs.com/package/gravatar). -- Otrzymany URL zapisz w polu `avatarURL` w czasie tworzenia użytkownika. - -## Krok 4 - -Dodaj możliwość aktualizacji awatara, tworząc endpoint `/users/avatars` i wykorzystując metodę `PATCH`. - -![avatar upload from postman](./avatar-upload.png) - -```shell -# Zapytanie -PATCH /users/avatars -Content-Type: multipart/form-data -Authorization: "Bearer {{token}}" -RequestBody: załadowany plik - -# Poprawna odpowiedź -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "avatarURL": "tu będzie odnośnik do obrazu" -} - -# Błędna odpowiedź -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -- Utwórz folder tmp w root projektu i zapisuj w nim załadowany awatar. -- Opracuj awatar przy pomocy pakietu [jimp](https://www.npmjs.com/package/jimp) i wprowadź dla niego wymiary 250 na 250. -- Przenieś awatar użytkownika z folderu tmp do folderu `public/avatars` i nadaj mu unikalną nazwę dla konkretnego użytkownika. -- Otrzymany `URL` `/avatars/` zapisz w polu `avatarURL` użytkownika. - -## Zadanie dodatkowe – nieobowiązkowe - -### 1. Napisać unit-testy dla kontrolera wejścia (login/signin) - -Przy pomocy [Jest](https://jestjs.io/ru/docs/getting-started) - -- odpowiedź powinna mieć status kod 200; -- w odpowiedzi powinien być zwracany token; -- w odpowiedzi powinien być zwracany obiekt `user` z 2 polami `email` i `subscription`, mającymi typ danych `String`. - diff --git a/homework-05/README.ua.md b/homework-05/README.ua.md deleted file mode 100755 index e5c117a..0000000 --- a/homework-05/README.ua.md +++ /dev/null @@ -1,80 +0,0 @@ -**Читати на інших мовах: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнє завдання 5 - -Створи гілку `hw05-avatars` з гілки ` master`. - -Продовж створення REST API для роботи з колекцією контактів. Додай можливість завантаження аватарки користувача через [Multer] (https://github.com/expressjs/multer). - -## Крок 1 - -Створи папку `public` для роздачі статики. У цій папці зроби папку `avatars`. Налаштуй Express на роздачу статичних файлів з папки `public`. - -Поклади будь-яке зображення в папку `public/avatars` і перевір, що роздача статики працює. При переході по такому URL браузер відобразить зображення. - -`` `Shell http://locahost:<порт>/avatars/<ім'я файлу з розширенням> `` ` - -## Крок 2 - -У схему користувача додай нову властивість `avatarURL` для зберігання зображення. - -```shell -{ - ... - avatarURL: String, - ... -} -``` - -- Використовуй пакет [gravatar](https://www.npmjs.com/package/gravatar) для того, щоб при реєстрації нового користувача відразу згенерувати йому аватар по його `email`. - -## Крок 3 - -При реєстрації користувача: - -- Створюй посилання на аватарку користувача за допомогою [gravatar](https://www.npmjs.com/package/gravatar) -- Отриманий URL збережи в поле `avatarURL` під час створення користувача - -## Крок 4 - -Додай можливість поновлення аватарки, створивши ендпоінт `/users/avatars` і використовуючи метод` PATCH`. - -![avatar upload from postman](./avatar-upload.png) - -```shell -# Запит -PATCH /users/avatars -Content-Type: multipart/form-data -Authorization: "Bearer {{token}}" -RequestBody: завантажений файл - -# Успішна відповідь -Status: 200 OK -Content-Type: application/json -ResponseBody: { - "avatarURL": "тут буде посилання на зображення" -} - -# Неуспішна відповідь -Status: 401 Unauthorized -Content-Type: application/json -ResponseBody: { - "message": "Not authorized" -} -``` - -- Створи папку `tmp` в корені проекту і зберігай в неї завантажену аватарку. -- Оброби аватарку пакетом [jimp](https://www.npmjs.com/package/jimp) і постав для неї розміри 250 на 250 -- Перенеси аватарку користувача з папки `tmp` в папку `public/avatars` і дай їй унікальне ім'я для конкретного користувача. -- Отриманий `URL` `/avatars/<ім'я файлу з розширенням>` та збережи в поле `avatarURL` користувача - -## Додаткове завдання - необов'язкове - -### 1. Написати unit-тести для контролера входу (login/signin) - -За допомогою [Jest](https://jestjs.io/ru/docs/getting-started) - -- відповідь повина мати статус-код 200 -- у відповіді повинен повертатися токен -- у відповіді повинен повертатися об'єкт `user` з 2 полями `email` та `subscription` з типом даних `String` - diff --git a/homework-05/avatar-upload.png b/homework-05/avatar-upload.png deleted file mode 100644 index 3851da655278c7872d8c8b945ef9922f5a61247d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72253 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 z 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 diff --git a/homework-05/controllers/auth/changeSubscription.js b/homework-05/controllers/auth/changeSubscription.js new file mode 100644 index 0000000..ba2afde --- /dev/null +++ b/homework-05/controllers/auth/changeSubscription.js @@ -0,0 +1,13 @@ +const changeSubscription = async (req, res) => { + const { _id } = req.user; + const { subscription } = req.body; + + await User.findByIdAndUpdate(_id, { subscription }); + + // Відправка відповіді клієнту зі статусом 200 (OK) та об'єктом, що містить повідомлення про зміну підписки. + res.json({ + message: `Your subscription has been changed to ${subscription}`, + }); +}; + +module.exports = changeSubscription; diff --git a/homework-05/controllers/auth/getCurrent.js b/homework-05/controllers/auth/getCurrent.js new file mode 100644 index 0000000..8612179 --- /dev/null +++ b/homework-05/controllers/auth/getCurrent.js @@ -0,0 +1,11 @@ +const getCurrent = async (req, res) => { + const { name, email, subscription } = req.user; + + res.json({ + name, + email, + subscription, + }); +}; + +module.exports = getCurrent; diff --git a/homework-05/controllers/auth/index.js b/homework-05/controllers/auth/index.js new file mode 100644 index 0000000..f6ced5c --- /dev/null +++ b/homework-05/controllers/auth/index.js @@ -0,0 +1,15 @@ +const register = require('./register'); +const login = require('./login'); +const logout = require('./logout'); +const getCurrent = require('./getCurrent'); +const changeSubscription = require('./changeSubscription'); +const updateAvatar = require('./updateAvatar'); + +module.exports = { + register, + login, + logout, + getCurrent, + changeSubscription, + updateAvatar, +}; diff --git a/homework-05/controllers/auth/login.js b/homework-05/controllers/auth/login.js new file mode 100644 index 0000000..e12124a --- /dev/null +++ b/homework-05/controllers/auth/login.js @@ -0,0 +1,44 @@ +const bcryptjs = require('bcryptjs'); // Підключення бібліотеки для шифрування паролей +const jwt = require('jsonwebtoken'); +const { User } = require('../../models/user'); +const { HttpError } = require('../../helpers'); +const { SECRET_KEY } = process.env; + +const login = async (req, res) => { + const { email, password } = req.body; + + // Пошук користувача в базі даних за його електронною поштою + const user = await User.findOne({ email }); + + if (!user) { + throw HttpError(401, 'Email or password is wrong'); + } + + // Порівняння введеного користувачем пароля з захешованим паролем з бази даних + const passwordCompare = await bcryptjs.compare(password, user.password); + + if (!passwordCompare) { + throw HttpError(401, 'Email or password is wrong'); + } + + // Створення пейлоада для JWT-токена, який містить ID користувача + const payload = { + id: user._id, + }; + + // Генерація JWT-токена з використанням пейлоада, секретного ключа та терміну дії токена + const token = jwt.sign(payload, SECRET_KEY, { expiresIn: '7d' }); + + // Оновлення користувача в базі даних, зберігаючи згенерований токен + await User.findByIdAndUpdate(user._id, { token }); + + res.json({ + token, + user: { + email: user.email, + subscription: user.subscription, + }, + }); +}; + +module.exports = login; diff --git a/homework-05/controllers/auth/logout.js b/homework-05/controllers/auth/logout.js new file mode 100644 index 0000000..5ebf5a9 --- /dev/null +++ b/homework-05/controllers/auth/logout.js @@ -0,0 +1,11 @@ +const { User } = require('../../models/user'); + +const logout = async (req, res) => { + const { _id } = req.user; + // Оновлення користувача в базі даних, встановивши поле `token` пустим рядком, що призведе до деактивації токена + await User.findByIdAndUpdate(_id, { token: '' }); + + res.status(204).json(); +}; + +module.exports = logout; diff --git a/homework-05/controllers/auth/register.js b/homework-05/controllers/auth/register.js new file mode 100644 index 0000000..c1efe96 --- /dev/null +++ b/homework-05/controllers/auth/register.js @@ -0,0 +1,24 @@ +const bcryptjs = require('bcryptjs'); // Підключення бібліотеки для хешування паролів +const { User } = require('../../models/user'); +const { HttpError } = require('../../helpers'); + +const register = async (req, res) => { + const { email, password } = req.body; + + // Перевірка, чи в базі даних вже існує користувач з таким email + const user = await User.findOne({ email }); + if (user) { + throw HttpError(409, 'Email in use'); + } + + const hashPassword = await bcryptjs.hash(password, 10); + + const newUser = await User.create({ ...req.body, password: hashPassword }); + + res.status(201).json({ + name: newUser.name, + email: newUser.email, + }); +}; + +module.exports = register; diff --git a/homework-05/controllers/auth/updateAvatar.js b/homework-05/controllers/auth/updateAvatar.js new file mode 100644 index 0000000..c2721a2 --- /dev/null +++ b/homework-05/controllers/auth/updateAvatar.js @@ -0,0 +1,56 @@ +const { User } = require('../../models/user'); +const path = require('path'); +const fs = require('fs/promises'); +const { HttpError, resizeImage } = require('../../helpers'); + +const avatarsDir = path.join(__dirname, '../../public/avatars'); + +// Тимчасова директорія для завантаження аватарів перед зміною розміру +const tempDir = path.join(__dirname, '../../temp'); + +const avatarExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff']; + +const updateAvatar = async (req, res) => { + const { _id } = req.user; + + // Отримання даних про завантажений аватар з об'єкту файлу, що був завантажений з допомогою multer + const { path: tempUpload, originalname } = req.file; + + const avatarName = `${_id}_${originalname}`; + + const fileExtension = originalname.substring(originalname.lastIndexOf('.') + 1); + + // Перевірка, чи відповідне розширення файлу знаходиться серед дозволених + if (!avatarExtensions.includes(fileExtension.toLowerCase())) { + throw new HttpError( + 400, + `${originalname} includes an invalid file extension! Must be: ${avatarExtensions.join(', or ')}`, + ); + } + + // Формуємо шлях до тимчасового файлу з аватаром + const tempImagePath = path.join(tempDir, avatarName); + + // Формуємо шлях до файлу з зміненим розміром (аватаром) у директорії public/avatars + const resizedImagePath = path.join(avatarsDir, avatarName); + + try { + // Перевіряємо, чи файл з аватаром вже існує у тимчасовій директорії + await fs.stat(tempImagePath); + } catch (error) { + // Якщо файл відсутній, це означає, що це перший раз завантажується аватар, + // тому ми копіюємо його без зміни розміру в тимчасову директорію + await fs.copyFile(tempUpload, tempImagePath); + } + + await resizeImage(tempImagePath, resizedImagePath); + + // Оновлюємо поле avatarURL в об'єкті користувача в базі даних за допомогою методу findByIdAndUpdate + await User.findByIdAndUpdate(_id, { avatarURL: path.join('avatars', avatarName) }); + + res.json({ + avatarURL: path.join('avatars', avatarName), + }); +}; + +module.exports = updateAvatar; diff --git a/homework-05/controllers/contacts/addContact.js b/homework-05/controllers/contacts/addContact.js new file mode 100644 index 0000000..8d53d38 --- /dev/null +++ b/homework-05/controllers/contacts/addContact.js @@ -0,0 +1,15 @@ +const addContact = async (req, res) => { + // Валідація даних контакту згідно схеми addSchema + const { error } = addSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing required name field'); + } + + const { _id: owner } = req.user; + + const result = await Contact.create({ ...req.body, owner }); + + res.status(201).json(result); +}; + +module.exports = addContact; diff --git a/homework-05/controllers/contacts/getById.js b/homework-05/controllers/contacts/getById.js new file mode 100644 index 0000000..609dfd6 --- /dev/null +++ b/homework-05/controllers/contacts/getById.js @@ -0,0 +1,14 @@ +const getById = async (req, res) => { + const { id } = req.params; + + const result = await Contact.findById(id); + + // Перевірка, чи був знайдений контакт за вказаним ідентифікатором + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = getById; diff --git a/homework-05/controllers/contacts/index.js b/homework-05/controllers/contacts/index.js new file mode 100644 index 0000000..b4a4ed2 --- /dev/null +++ b/homework-05/controllers/contacts/index.js @@ -0,0 +1,15 @@ +const listContacts = require('./listContacts'); +const getById = require('./getById'); +const addContact = require('./addContact'); +const updateById = require('./updateById'); +const updateStatusContact = require('./updateStatusContact'); +const removeContact = require('./removeContact'); + +module.exports = { + listContacts, + getById, + addContact, + updateById, + updateStatusContact, + removeContact, +}; diff --git a/homework-05/controllers/contacts/listContacts.js b/homework-05/controllers/contacts/listContacts.js new file mode 100644 index 0000000..cf7ff96 --- /dev/null +++ b/homework-05/controllers/contacts/listContacts.js @@ -0,0 +1,26 @@ +const listContacts = async (req, res) => { + const { _id: owner } = req.user; + const { page = 1, limit = 10 } = req.query; + + // Обчислення кількості пропущених контактів (skip) відповідно до номера сторінки та кількості елементів на сторінці + const skip = (page - 1) * limit; + + if (req.query.favorite) { + // Визначення, чи користувач хоче побачити улюблені контакти (значення 'true' або 'false') + const favorite = req.query.favorite === 'true'; + + // Пошук контактів у базі даних, які належать користувачу (owner) та є або не є улюбленими (відповідно до параметра 'favorite') + const result = await Contact.find({ owner, favorite }, '', { + skip, + limit, + }).populate('owner', 'name email'); + return res.json(result); + } + + // Якщо в запиті не вказано, що показувати улюблені контакти, виконується пошук всіх контактів користувача + const result = await Contact.find({ owner }, '', { skip, limit }).populate('owner', 'name email'); + + res.json(result); +}; + +module.exports = listContacts; diff --git a/homework-05/controllers/contacts/removeContact.js b/homework-05/controllers/contacts/removeContact.js new file mode 100644 index 0000000..51aa5a6 --- /dev/null +++ b/homework-05/controllers/contacts/removeContact.js @@ -0,0 +1,16 @@ +const removeContact = async (req, res) => { + const { id } = req.params; + + const result = await Contact.findByIdAndDelete(id); + + // Перевірка, чи було успішне видалення контакту + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json({ + message: 'contact deleted', + }); +}; + +module.exports = removeContact; diff --git a/homework-05/controllers/contacts/updateById.js b/homework-05/controllers/contacts/updateById.js new file mode 100644 index 0000000..fd78fde --- /dev/null +++ b/homework-05/controllers/contacts/updateById.js @@ -0,0 +1,20 @@ +const updateById = async (req, res) => { + // Перевірка валідності даних контакту з тілом запиту згідно схеми addSchema + const { error } = addSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing fields'); + } + + const { id } = req.params; + + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + + // Перевірка, чи було успішне оновлення контакту + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateById; diff --git a/homework-05/controllers/contacts/updateStatusContact.js b/homework-05/controllers/contacts/updateStatusContact.js new file mode 100644 index 0000000..221e563 --- /dev/null +++ b/homework-05/controllers/contacts/updateStatusContact.js @@ -0,0 +1,20 @@ +const updateStatusContact = async (req, res) => { + // Перевірка валідності поля favorite у тілі запиту згідно схеми updateFavoriteSchema + const { error } = updateFavoriteSchema.validate(req.body); + if (error) { + throw HttpError(400, 'missing field favorite'); + } + + const { id } = req.params; + + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); + + // Перевірка, чи було успішне оновлення контакту + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateStatusContact; diff --git a/homework-05/helpers/HttpError.js b/homework-05/helpers/HttpError.js new file mode 100644 index 0000000..67d68a4 --- /dev/null +++ b/homework-05/helpers/HttpError.js @@ -0,0 +1,7 @@ +const HttpError = (status, message) => { + const error = new Error(message); + error.status = status; // Додавання властивості "status" з переданим статусом до об'єкту помилки + return error; +}; + +module.exports = HttpError; // Експорт функції HttpError для використання її в інших модулях проекту diff --git a/homework-05/helpers/ctrlWrapper.js b/homework-05/helpers/ctrlWrapper.js new file mode 100644 index 0000000..8d3e6fb --- /dev/null +++ b/homework-05/helpers/ctrlWrapper.js @@ -0,0 +1,14 @@ +const ctrlWrapper = ctrl => { + const func = async (req, res, next) => { + try { + // Виклик контролера з передачею йому об'єкта запиту (req), об'єкта відповіді (res) та функції next + await ctrl(req, res, next); + } catch (error) { + next(error); + } + }; + + return func; +}; + +module.exports = ctrlWrapper; diff --git a/homework-05/helpers/handleMongooseError.js b/homework-05/helpers/handleMongooseError.js new file mode 100644 index 0000000..d30bcf2 --- /dev/null +++ b/homework-05/helpers/handleMongooseError.js @@ -0,0 +1,11 @@ +const handleMongooseError = (error, data, next) => { + const { name, code } = error; + // Якщо помилка є MongoDB Duplicate Key Error (код 11000), статус 409 - Conflict + // В інших випадках, статус 400 - Bad Request + const status = name === 'MongoServerError' && code === 11000 ? 409 : 400; + // Додавання статусу до об'єкту помилки + error.status = status; + next(); +}; + +module.exports = handleMongooseError; diff --git a/homework-05/helpers/index.js b/homework-05/helpers/index.js new file mode 100644 index 0000000..a2d0670 --- /dev/null +++ b/homework-05/helpers/index.js @@ -0,0 +1,11 @@ +const HttpError = require('./HttpError'); +const ctrlWrapper = require('./ctrlWrapper'); +const handleMongooseError = require('./handleMongooseError'); +const resizeImage = require('./resizeImage'); + +module.exports = { + HttpError, + ctrlWrapper, + handleMongooseError, + resizeImage, +}; diff --git a/homework-05/helpers/resizeImage.js b/homework-05/helpers/resizeImage.js new file mode 100644 index 0000000..5f10f65 --- /dev/null +++ b/homework-05/helpers/resizeImage.js @@ -0,0 +1,10 @@ +const Jimp = require('jimp'); // Підключення бібліотеки Jimp для роботи з зображеннями + +const resizeImage = async (sourcePath, destinationPath) => { + // Асинхронна функція для зміни розміру зображення + const image = await Jimp.read(sourcePath); // Зчитування вихідного зображення з вказаного шляху + image.resize(250, 250); + await image.writeAsync(destinationPath); // Збереження зменшеного зображення за вказаним шляхом +}; + +module.exports = resizeImage; diff --git a/homework-05/middlewares/authenticate.js b/homework-05/middlewares/authenticate.js new file mode 100644 index 0000000..b324a91 --- /dev/null +++ b/homework-05/middlewares/authenticate.js @@ -0,0 +1,34 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models/user'); + +require('dotenv').config(); +const { SECRET_KEY } = process.env; + +const { HttpError } = require('../helpers'); + +const authenticate = async (req, res, next) => { + const { authorization = '' } = req.headers; // Отримання заголовку Authorization з запиту, якщо такий існує + const [bearer, token] = authorization.split(' '); // Розділення токена на частини по пробілу + + if (bearer !== 'Bearer') { + // Перевірка на наявність токена та перевірка його типу + next(HttpError(401, 'Not authorized')); // Якщо токен не валідний, викликаємо функцію HttpError зі статусом 401 та повідомленням про помилку + } + + try { + const { id } = jwt.verify(token, SECRET_KEY); + const user = await User.findById(id); + if (!user || !user.token || user.token !== token) { + // Перевірка чи користувач з таким id існує та чи токен співпадає з токеном з бази даних + next(HttpError(401, 'Not authorized')); + } + + req.user = user; + + next(); // Переходимо до наступного middleware + } catch { + next(HttpError(401, 'Not authorized')); + } +}; + +module.exports = authenticate; diff --git a/homework-05/middlewares/index.js b/homework-05/middlewares/index.js new file mode 100644 index 0000000..f0fc7f7 --- /dev/null +++ b/homework-05/middlewares/index.js @@ -0,0 +1,5 @@ +const isValidId = require('./isValidId'); +const authenticate = require('./authenticate'); +const validateBody = require('./validateBody'); +const upload = require('./upload'); +module.exports = { isValidId, authenticate, validateBody, upload }; diff --git a/homework-05/middlewares/isValidId.js b/homework-05/middlewares/isValidId.js new file mode 100644 index 0000000..719e4c6 --- /dev/null +++ b/homework-05/middlewares/isValidId.js @@ -0,0 +1,14 @@ +const { isValidObjectId } = require('mongoose'); +const { HttpError } = require('../helpers'); + +const isValidId = (req, res, next) => { + const { id } = req.params; + + if (!isValidObjectId(id)) { + next(HttpError(400, `${id} is not valid id`)); + } + + next(); // Якщо id валідний, переходимо до наступного middleware +}; + +module.exports = isValidId; diff --git a/homework-05/middlewares/upload.js b/homework-05/middlewares/upload.js new file mode 100644 index 0000000..495de58 --- /dev/null +++ b/homework-05/middlewares/upload.js @@ -0,0 +1,19 @@ +const multer = require('multer'); // Імпорт бібліотеки multer для обробки завантаження файлів +const path = require('path'); + +const tempDir = path.join(__dirname, '../', 'temp'); // Шлях до тимчасової директорії для збереження завантажених файлів + +const multerConfig = multer.diskStorage({ + destination: tempDir, // Встановлення шляху до директорії, де будуть зберігатись тимчасово завантажені файли + filename: (req, file, cb) => { + // Функція для визначення імені завантаженого файлу + cb(null, file.originalname); // Встановлення оригінального імені файлу для збереження + }, +}); + +const upload = multer({ + // Створення middleware для завантаження файлів з використанням налаштувань multerConfig + storage: multerConfig, +}); + +module.exports = upload; diff --git a/homework-05/middlewares/validateBody.js b/homework-05/middlewares/validateBody.js new file mode 100644 index 0000000..861daee --- /dev/null +++ b/homework-05/middlewares/validateBody.js @@ -0,0 +1,17 @@ +const { HttpError } = require('../helpers'); + +const validateBody = schema => { + const func = (req, res, next) => { + const { error } = schema.validate(req.body); + + if (error) { + next(HttpError(400, error.message)); + } + + next(); // Якщо валідація успішна, переходимо до наступного middleware + }; + + return func; +}; + +module.exports = validateBody; diff --git a/homework-05/models/contact.js b/homework-05/models/contact.js new file mode 100644 index 0000000..3dcb287 --- /dev/null +++ b/homework-05/models/contact.js @@ -0,0 +1,44 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const contactSchema = new Schema( + { + name: { + type: String, + required: [true, 'Set name for contact'], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, + owner: { + type: Schema.Types.ObjectId, + ref: 'user', // Посилання на колекцію "user" + required: true, + }, + }, + { versionKey: false }, // Прибирає ключ __v з документів у базі даних +); + +contactSchema.post('save', handleMongooseError); + +const Contact = model('contact', contactSchema); + +const addSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().required(), + phone: Joi.string().required(), +}); + +const updateFavoriteSchema = Joi.object({ + favorite: Joi.boolean().required(), +}); + +module.exports = { Contact, addSchema, updateFavoriteSchema }; diff --git a/homework-05/models/user.js b/homework-05/models/user.js new file mode 100644 index 0000000..bee944f --- /dev/null +++ b/homework-05/models/user.js @@ -0,0 +1,73 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const emailRegexp = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/; +const subscriptionList = ['starter', 'pro', 'business']; + +const userSchema = new Schema( + { + name: { + type: String, + required: true, + }, + email: { + type: String, + match: emailRegexp, + required: [true, 'Email is required'], + unique: true, + }, + password: { + type: String, + minlength: 6, + required: [true, 'Set password for user'], + }, + + subscription: { + type: String, + enum: subscriptionList, + default: 'starter', + }, + token: { + type: String, + default: '', // Поле "token" за замовчуванням є пустим рядком + }, + avatarURL: { + type: String, + required: true, + }, + }, + { versionKey: false }, // Прибирає ключ __v з документів у базі даних +); + +userSchema.post('save', handleMongooseError); + +const registerSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().pattern(emailRegexp).required(), + password: Joi.string().min(6).required(), +}); + +const loginSchema = Joi.object({ + email: Joi.string().required(), + password: Joi.string().min(6).required(), +}); + +const changeSubscriptionSchema = Joi.object({ + subscription: Joi.string() + .valid(...subscriptionList) + .required(), +}); + +const User = model('user', userSchema); + +const schemas = { + registerSchema, + loginSchema, + changeSubscriptionSchema, +}; + +module.exports = { + User, + schemas, +}; diff --git a/homework-05/nodemon.json b/homework-05/nodemon.json new file mode 100644 index 0000000..54d6947 --- /dev/null +++ b/homework-05/nodemon.json @@ -0,0 +1,3 @@ +{ + "ignore": ["node_modules", "models/contacts.json"] +} diff --git a/homework-05/public/avatars/.gitkeep b/homework-05/public/avatars/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/homework-05/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg b/homework-05/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86e804f8e53c4cf437efd1e8bde57ae0b8bdad1b GIT binary patch literal 7676 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 O{@+!^+3z6Y=>G!AvcYfw literal 0 HcmV?d00001 diff --git a/homework-05/routes/api/auth.js b/homework-05/routes/api/auth.js new file mode 100644 index 0000000..db18d06 --- /dev/null +++ b/homework-05/routes/api/auth.js @@ -0,0 +1,31 @@ +const express = require('express'); +const { validateBody, authenticate, upload } = require('../../middlewares'); +const { schemas } = require('../../models/user'); + +const router = express.Router(); + +const ctrl = require('../../controllers/auth'); +const { ctrlWrapper } = require('../../helpers'); + +router.post( + '/register', + validateBody(schemas.registerSchema), + ctrlWrapper(ctrl.register), // Обробка запиту контролером register +); + +router.post('/login', validateBody(schemas.loginSchema), ctrlWrapper(ctrl.login)); + +router.get('/current', authenticate, ctrlWrapper(ctrl.getCurrent)); // Встановлення маршруту GET з middleware автентифікації до обробки контролером getCurrent + +router.post('/logout', authenticate, ctrlWrapper(ctrl.logout)); + +router.patch( + '/users/avatars', + authenticate, + upload.single('avatar'), // Використання middleware upload для завантаження одного файла з ім'ям "avatar" + ctrlWrapper(ctrl.updateAvatar), // Обробка запиту контролером updateAvatar +); + +router.patch('/', authenticate, validateBody(schemas.changeSubscriptionSchema), ctrlWrapper(ctrl.changeSubscription)); + +module.exports = router; diff --git a/homework-05/routes/api/contacts.js b/homework-05/routes/api/contacts.js new file mode 100644 index 0000000..fb235e7 --- /dev/null +++ b/homework-05/routes/api/contacts.js @@ -0,0 +1,16 @@ +const express = require('express'); +const router = express.Router(); + +const ctrl = require('../../controllers/contacts'); +const { ctrlWrapper } = require('../../helpers'); + +const { isValidId, authenticate } = require('../../middlewares'); + +router.get('/', authenticate, ctrlWrapper(ctrl.listContacts)); +router.get('/:id', authenticate, isValidId, ctrlWrapper(ctrl.getById)); +router.post('/', authenticate, ctrlWrapper(ctrl.addContact)); +router.put('/:id', authenticate, isValidId, ctrlWrapper(ctrl.updateById)); +router.patch('/:id/favorite', authenticate, isValidId, ctrlWrapper(ctrl.updateStatusContact)); +router.delete('/:id', authenticate, isValidId, ctrlWrapper(ctrl.removeContact)); + +module.exports = router; diff --git a/homework-05/server.js b/homework-05/server.js new file mode 100644 index 0000000..1ee1d63 --- /dev/null +++ b/homework-05/server.js @@ -0,0 +1,16 @@ +const mongoose = require('mongoose'); +const app = require('./app'); +const { DB_HOST } = process.env; + +mongoose + .connect(DB_HOST) + .then(() => { + console.log('Database connection successful'); + app.listen(3000, () => { + console.log('Server running. Use our API on port: 3000'); + }); + }) + .catch(error => { + console.log(error.message); + process.exit(1); // Завершити процес з кодом 1, щоб позначити, що виникла помилка + }); diff --git a/homework-05/temp/.gitkeep b/homework-05/temp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/homework-05/temp/649c7f75733d3ba6bb281c92_avatar (2).jpg b/homework-05/temp/649c7f75733d3ba6bb281c92_avatar (2).jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef6fac6f54103589bf648cdb4b20894a50b25f4d GIT binary patch literal 43425 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 literal 0 HcmV?d00001 diff --git a/homework-05/temp/avatar.jpg b/homework-05/temp/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef6fac6f54103589bf648cdb4b20894a50b25f4d GIT binary patch literal 43425 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 literal 0 HcmV?d00001 From 3ec39113242f168d8fa124bfcd0fc4eb3654eebb Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Fri, 28 Jul 2023 22:38:33 +0300 Subject: [PATCH 8/9] Delete api-key.png --- homework-06/api-key.png | Bin 17262 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 homework-06/api-key.png diff --git a/homework-06/api-key.png b/homework-06/api-key.png deleted file mode 100644 index 76a997888dd90ec3f3ca7202fa69de219374358f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 17262 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 From 1a4cabc05771947540b9c111c2b48ff58d1fc9cc Mon Sep 17 00:00:00 2001 From: Dmytrii Beresten Date: Sat, 29 Jul 2023 19:38:53 +0300 Subject: [PATCH 9/9] homework --- ...> 64a581f17ab9d2f81652c536_avatar.jpg.jpg} | Bin ...> 64a581f17ab9d2f81652c536_avatar.jpg.jpg} | Bin homework-06/.eslintignore | 1 + homework-06/.eslintrc.js | 12 ++ homework-06/.gitignore | 4 + homework-06/README.en.md | 154 ----------------- homework-06/README.es.md | 155 ----------------- homework-06/README.md | 156 +----------------- homework-06/README.pl.md | 155 ----------------- homework-06/README.ua.md | 154 ----------------- .../controllers/auth/changeSubscription.js | 13 ++ homework-06/controllers/auth/getCurrent.js | 11 ++ homework-06/controllers/auth/index.js | 19 +++ homework-06/controllers/auth/login.js | 40 +++++ homework-06/controllers/auth/logout.js | 10 ++ homework-06/controllers/auth/register.js | 44 +++++ .../controllers/auth/resendVerifyEmail.js | 31 ++++ homework-06/controllers/auth/updateAvatar.js | 43 +++++ homework-06/controllers/auth/verifyEmail.js | 22 +++ .../controllers/contacts/addContact.js | 17 ++ homework-06/controllers/contacts/getById.js | 13 ++ homework-06/controllers/contacts/index.js | 15 ++ .../controllers/contacts/listContacts.js | 22 +++ .../controllers/contacts/removeContact.js | 17 ++ .../controllers/contacts/updateById.js | 21 +++ .../contacts/updateStatusContact.js | 21 +++ homework-06/helpers/HttpError.js | 7 + homework-06/helpers/ctrlWrapper.js | 13 ++ homework-06/helpers/handleMongooseError.js | 8 + homework-06/helpers/index.js | 13 ++ homework-06/helpers/resizeImage.js | 9 + homework-06/helpers/sendEmail.js | 14 ++ homework-06/middlewares/authenticate.js | 33 ++++ homework-06/middlewares/index.js | 5 + homework-06/middlewares/isValidId.js | 14 ++ homework-06/middlewares/upload.js | 17 ++ homework-06/middlewares/validateBody.js | 15 ++ homework-06/models/contact.js | 48 ++++++ homework-06/models/user.js | 89 ++++++++++ homework-06/node.png | Bin 35439 -> 0 bytes homework-06/nodemon.json | 3 + homework-06/public/avatars/.gitkeep | 0 .../649c7f75733d3ba6bb281c92_avatar.jpg | Bin 0 -> 7676 bytes .../64a581f17ab9d2f81652c536_avatar.jpg | Bin 0 -> 7676 bytes homework-06/routes/api/auth.js | 28 ++++ homework-06/routes/api/contacts.js | 23 +++ homework-06/sender-not-verify.png | Bin 11936 -> 0 bytes homework-06/sender-verify.png | Bin 11988 -> 0 bytes homework-06/server.js | 17 ++ homework-06/temp/.gitkeep | 0 .../temp/649c7f75733d3ba6bb281c92_avatar.jpg | Bin 0 -> 43425 bytes .../temp/64a581f17ab9d2f81652c536_avatar.jpg | Bin 0 -> 43425 bytes homework-06/temp/avatar.jpg | Bin 0 -> 43425 bytes homework-06/web-api.png | Bin 35520 -> 0 bytes 54 files changed, 733 insertions(+), 773 deletions(-) rename homework-05/public/avatars/{649c7f75733d3ba6bb281c92_avatar.jpg => 64a581f17ab9d2f81652c536_avatar.jpg.jpg} (100%) rename homework-05/temp/{649c7f75733d3ba6bb281c92_avatar (2).jpg => 64a581f17ab9d2f81652c536_avatar.jpg.jpg} (100%) create mode 100644 homework-06/.eslintignore create mode 100644 homework-06/.eslintrc.js create mode 100644 homework-06/.gitignore delete mode 100644 homework-06/README.en.md delete mode 100644 homework-06/README.es.md delete mode 100644 homework-06/README.pl.md delete mode 100755 homework-06/README.ua.md create mode 100644 homework-06/controllers/auth/changeSubscription.js create mode 100644 homework-06/controllers/auth/getCurrent.js create mode 100644 homework-06/controllers/auth/index.js create mode 100644 homework-06/controllers/auth/login.js create mode 100644 homework-06/controllers/auth/logout.js create mode 100644 homework-06/controllers/auth/register.js create mode 100644 homework-06/controllers/auth/resendVerifyEmail.js create mode 100644 homework-06/controllers/auth/updateAvatar.js create mode 100644 homework-06/controllers/auth/verifyEmail.js create mode 100644 homework-06/controllers/contacts/addContact.js create mode 100644 homework-06/controllers/contacts/getById.js create mode 100644 homework-06/controllers/contacts/index.js create mode 100644 homework-06/controllers/contacts/listContacts.js create mode 100644 homework-06/controllers/contacts/removeContact.js create mode 100644 homework-06/controllers/contacts/updateById.js create mode 100644 homework-06/controllers/contacts/updateStatusContact.js create mode 100644 homework-06/helpers/HttpError.js create mode 100644 homework-06/helpers/ctrlWrapper.js create mode 100644 homework-06/helpers/handleMongooseError.js create mode 100644 homework-06/helpers/index.js create mode 100644 homework-06/helpers/resizeImage.js create mode 100644 homework-06/helpers/sendEmail.js create mode 100644 homework-06/middlewares/authenticate.js create mode 100644 homework-06/middlewares/index.js create mode 100644 homework-06/middlewares/isValidId.js create mode 100644 homework-06/middlewares/upload.js create mode 100644 homework-06/middlewares/validateBody.js create mode 100644 homework-06/models/contact.js create mode 100644 homework-06/models/user.js delete mode 100644 homework-06/node.png create mode 100644 homework-06/nodemon.json create mode 100644 homework-06/public/avatars/.gitkeep create mode 100644 homework-06/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg create mode 100644 homework-06/public/avatars/64a581f17ab9d2f81652c536_avatar.jpg create mode 100644 homework-06/routes/api/auth.js create mode 100644 homework-06/routes/api/contacts.js delete mode 100644 homework-06/sender-not-verify.png delete mode 100644 homework-06/sender-verify.png create mode 100644 homework-06/server.js create mode 100644 homework-06/temp/.gitkeep create mode 100644 homework-06/temp/649c7f75733d3ba6bb281c92_avatar.jpg create mode 100644 homework-06/temp/64a581f17ab9d2f81652c536_avatar.jpg create mode 100644 homework-06/temp/avatar.jpg delete mode 100644 homework-06/web-api.png diff --git a/homework-05/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg b/homework-05/public/avatars/64a581f17ab9d2f81652c536_avatar.jpg.jpg similarity index 100% rename from homework-05/public/avatars/649c7f75733d3ba6bb281c92_avatar.jpg rename to homework-05/public/avatars/64a581f17ab9d2f81652c536_avatar.jpg.jpg diff --git a/homework-05/temp/649c7f75733d3ba6bb281c92_avatar (2).jpg b/homework-05/temp/64a581f17ab9d2f81652c536_avatar.jpg.jpg similarity index 100% rename from homework-05/temp/649c7f75733d3ba6bb281c92_avatar (2).jpg rename to homework-05/temp/64a581f17ab9d2f81652c536_avatar.jpg.jpg diff --git a/homework-06/.eslintignore b/homework-06/.eslintignore new file mode 100644 index 0000000..b512c09 --- /dev/null +++ b/homework-06/.eslintignore @@ -0,0 +1 @@ +node_modules \ No newline at end of file diff --git a/homework-06/.eslintrc.js b/homework-06/.eslintrc.js new file mode 100644 index 0000000..d799332 --- /dev/null +++ b/homework-06/.eslintrc.js @@ -0,0 +1,12 @@ +module.exports = { + env: { + commonjs: true, + es2021: true, + node: true, + }, + extends: ['standard', 'prettier'], + parserOptions: { + ecmaVersion: 12, + }, + rules: {}, +} diff --git a/homework-06/.gitignore b/homework-06/.gitignore new file mode 100644 index 0000000..8877fc5 --- /dev/null +++ b/homework-06/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +.env +.idea +.vscode \ No newline at end of file diff --git a/homework-06/README.en.md b/homework-06/README.en.md deleted file mode 100644 index 305ec42..0000000 --- a/homework-06/README.en.md +++ /dev/null @@ -1,154 +0,0 @@ -**Read in other languages: [Russian](README.md), [Ukrainian](README.ua.md).** - -# Homework 6 - -Create branch `hw06-email` from branch `master`. - -We continue to create a REST API for working with a collection of contacts. Add user email verification after registration using the [SendGrid](https://sendgrid.com/) service. - -## How the Verification Process Should Work - -1. After registration, the user should receive a letter to the email address specified during registration with a link to verify his email -2. After clicking the link in the received email for the first time, the user should receive a [Response with status 200](#verification-success-response), which will imply successful email verification -3. After clicking on the link again, the user should get [Error with status 404](#verification-user-not-found) - -## Step 1 - -### Preparing Integration with SendGrid API - -- Register at [SendGrid](https://sendgrid.com/) -- Create an email sender. To do this, in the SendGrid administrative panel, go to the Marketing menu in the senders submenu and click the "Create New Sender" button in the upper right corner. Fill in the required fields in the proposed form. Save. You should get the following result as in the picture, only with your email instead. - -![sender](sender-not-verify.png) - -A verification email should be sent to the specified email address (check spam if you don't see the email). Click on the link in it and complete the process. The result should change to: - -![sender](sender-verify.png) - -- Now you need to create an API access token. Select the "Email API" menu, and the "Integration Guide" submenu. Here we select "Web API" - -![api-key](web-api.png) - -Next, you need to select the Node.js technology - -![api-key](node.png) - -In the third step, we give a name to our token. For example systemcats, we press the generate button and we get the result as in the screenshot below. You need to copy this token (this is important because you won't be able to see it anymore). After completing the token creation process: - -![api-key](api-key.png) - -- The resulting API token must be added to the `.env` file in our project - -## Step 2 - -### Create an Endpoint for Email Verification - -- Add two fields `verificationToken` and `verify` to the `User` model. A value of the `verify` field equal to `false` will mean that his email has not been verified yet. - -```js -{ - verify: { - type: Boolean, - default: false, - }, - verificationToken: { - type: String, - required: [true, 'Verify token is required'], - }, -} -``` - -- Create a GET [`/users/verify/:verificationToken`](#verification-request) endpoint, where we will search for a user in the `User` model by the `verificationToken` parameter. -- If user with such token is not found, return [Error 'Not Found'](#verification-user-not-found) -- If the user is found - set `verificationToken` to `null`, and set the `verify` field to `true` in the user document and return [Successful response](#verification-success-response) - -### Verification Request - -```shell -GET /users/verify/:verificationToken -``` - -### Verification User Not Found - -```shell -Status: 404 Not Found -ResponseBody: { - message: 'User not found' -} -``` - -### Verification Success Response - -```shell -Status: 200 OK -ResponseBody: { - message: 'Verification successful', -} -``` - -## Step 3 - -### Adding an Email to the User with a Verificaton Link - -When creating a user during registration: - -- Create a `verificationToken` for the user and write it to the database (to generate a token, use the package [uuid](https://www.npmjs.com/package/uuid) or [nanoid](https://www.npmjs.com /package/nanoid)) -- Send an email to the user's mail and specify a link to verify the email (`/users/verify/:verificationToken`) in the message -- It is also necessary to take into account that now the user login is not allowed with an unverified email - -## Step 4 - -### Adding a Resend Email to the User with a Verification Link - -It is necessary to provide for the option that the user can accidentally delete the letter. It may not reach the addressee for some reason. Our service for sending letters during registration gave an error, etc. - -#### @ POST /users/verify/ - -- Gets `body` in `{ email }` format -- If there is no required field `email` in `body`, returns JSON with key `{"message": "missing required field email"}` and status `400` -- If everything is fine with `body`, resend the letter with `verificationToken` to the specified email, but only if the user is not verified -- If the user has already passed verification, send json with the key `{ message: "Verification has already been passed"}` with status `400 Bad Request` - -#### Resending an Email Request - -```shell -POST /users/verify -Content-Type: application/json -RequestBody: { - "email": "example@example.com" -} -``` - -#### Resending an Email Validation Error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Resending an Email Success Response - -```shell -Status: 200 Ok -Content-Type: application/json -ResponseBody: { - "message": "Verification email sent" -} -``` - -#### Resend Email for Verified User - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: { - message: "Verification has already been passed" -} -``` - -> Note: As an alternative to SendGrid, you can use the [nodemailer] package(https://www.npmjs.com/package/nodemailer) - -## Additional Task - Optional - -### 1. Write a dockerfile for your application diff --git a/homework-06/README.es.md b/homework-06/README.es.md deleted file mode 100644 index c0bd115..0000000 --- a/homework-06/README.es.md +++ /dev/null @@ -1,155 +0,0 @@ -**Leer en otros idiomas: [Русский](README.md), [Українська](README.ua.md).** - -# Tarea 6 - -Crea una rama `hw06-email` de la rama `master`. - -Continuamos construyendo la API REST para la manipulación de colecciones de contactos. Añade la verificación del email del usuario después de registrarse, mediante el servicio [SendGrid](https://sendgrid.com/). - -## Cómo debe funcionar el proceso de verificación - -1. Después de registrarse, el usuario debería recibir un mensaje de correo electrónico en la dirección facilitada durante el registro con un enlace para verificar su email -2. Al seguir el enlace en el correo recibido la primera vez, el usuario debería recibir una [Respuesta con el estado 200](#verification-success-response), lo que significaría la verificación exitosa del correo electrónico -3. Al seguir de nuevo el enlace, el usuario debería recibir [Error con el estado 404](#verification-user-not-found) - -## Paso 1 - -### Preparando la integración con SendGrid API - -- Regístrate en [SendGrid](https://sendgrid.com/). -- Crea un remitente de correo electrónico. Para ello, en el panel de administración de SendGrid, vaya al menú Marketing en el submenú senders y en la esquina superior derecha haz clic en "Create New Sender". Rellena los campos obligatorios del formulario propuesto. Guárdalo. Deberías obtener el siguiente resultado como en la imagen, sólo que con tu email: - -![sender](sender-not-verify.png) - -Debería enviarse un correo de verificación al email especificado (comprueba el correo no deseado si no lo ves). Haz clic en el enlace que aparece en él y completa el proceso. El resultado debería cambiar a: - -![sender](sender-verify.png) - -- Ahora necesitas crear un token de acceso a la API. Selecciona el menú "Email API" y el submenú "Integration Guide". Aquí seleccione "Web API" - -![api-key](web-api.png) - -A continuación, seleccione la tecnología Node.js - -![api-key](node.png) - -En el tercer paso, le damos un nombre a nuestro token. Por ejemplo, systemcats, pulse el botón de generar y obtenga el resultado como se muestra en la captura de pantalla siguiente. Tienes que copiar este token (esto es importante porque no podrás volver a verlo). Después de completar el proceso de creación del token - -![api-key](api-key.png) - -- El token de la API obtenido debe añadirse al archivo `.env` de nuestro proyecto - -## Paso 2 - -### Creación de un endpoint para la verificación del email - -- añade dos campos `verificationToken` y `verify` al modelo `User`. Si el valor del campo `verify` igual a `false` significa que su correo electrónico aún no ha sido verificado. - -```js -{ - verify: { - type: Boolean, - default: false, - }, - verificationToken: { - type: String, - required: [true, 'Verify token is required'], - }, -} -``` - -- crea el endpoint GET [`/users/verify/:verificationToken`](#verification-request), donde para buscar un usuario en el modelo `User` se utilizaremos el parámetro `verificationToken` -- si no se encuentra un usuario con este token, debe devolver [Error 'Not Found'](#verification-user-not-found) -- si el usuario es encontrado, se establece `verificationToken` a `null` y se establece el campo `verify` a `true` en el documento del usuario, y se devuelve [Respuesta exitosa](#verification-success-response) - -### Verification request - -```shell -GET /users/verify/:verificationToken -``` - -### Verification user Not Found - -```shell -Status: 404 Not Found -ResponseBody: { - message: 'User not found' -} -``` - -### Verification success response - -```shell -Status: 200 OK -ResponseBody: { - message: 'Verification successful', -} -``` - -## Paso 3 - -### Añadir el correo electrónico al usuario con un enlace de verificación - -Al crear un usuario durante el registro: - -- se crea `verificationToken` para el usuario y se escribe en la base de datos (para generar el token, utilice el paquete [uuid](https://www.npmjs.com/package/uuid) o [nanoid](https://www.npmjs.com/package/nanoid)) -- Se envía un correo electrónico al usuario y se proporciona un enlace para verificar el email (`/users/verify/:verificationToken`) en el mensaje -- También hay que tener en cuenta que ahora no se permite el inicio de sesión del usuario si el correo electrónico no está verificado - -## Paso 4 - -### Realizar un reenvío del correo al usuario con el enlace de verificación - -Es posible que el usuario pueda borrar accidentalmente el correo electrónico. Puede que no llegue al destinatario por alguna razón, o que nuestro servicio de envío de correos electrónicos haya tenido un error durante el registro, etc. - -#### @ POST /users/verify/ - -- Recibe `body` en formato `{ email }` -- Si en `body` no existe el campo obligatorio `email`, devuelve un json con la llave `{"message": "missing required field email"}` y el estado `400` -- Si en `body` todo está bien, reenviamos el correo electrónico con un `verificationToken` al email especificado, pero sólo si el usuario no está verificado -- Si el usuario ya ha sido verificado, envía un json con la llave `{ message: "Verification has already been passed"}` con el estado `400 Bad Request` - -#### Resending a email request - -```shell -POST /users/verify -Content-Type: application/json -RequestBody: { - "email": "example@example.com" -} -``` - -#### Resending a email validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Resending a email success response - -```shell -Status: 200 Ok -Content-Type: application/json -ResponseBody: { - "message": "Verification email sent" -} -``` - -#### Resend email for verified user - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: { - message: "Verification has already been passed" -} -``` - -> Nota: Como alternativa a SendGrid, puede utilizar el paquete [nodemailer](https://www.npmjs.com/package/nodemailer) - -## Tarea adicional (opcional) - -### 1. Escriba un dockerfile para su aplicación - diff --git a/homework-06/README.md b/homework-06/README.md index 240110c..79af6d6 100644 --- a/homework-06/README.md +++ b/homework-06/README.md @@ -1,155 +1 @@ -**Читать на других языках: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнее задание 6 - -Создай ветку `hw06-email` из ветки `master`. - -Продолжаем создание REST API для работы с коллекцией контактов. Добавьте верификацию email пользователя после регистрации при помощи сервиса [SendGrid](https://sendgrid.com/). - -## Как процесс верификации должен работать - -1. После регистрации, пользователь должен получить письмо на указанную при регистрации почту с ссылкой для верификации своего email -2. Пройдя ссылке в полученном письме, в первый раз, пользователь должен получить [Ответ со статусом 200](#verification-success-response), что будет подразумевать успешную верификацию email -3. Пройдя по ссылке повторно пользователь должен получить [Ошибку со статусом 404](#verification-user-not-found) - -## Шаг 1 - -### Подготовка интеграции с SendGrid API - -- Зарегистрируйся на [SendGrid](https://sendgrid.com/). -- Создай email-отправителя. Для это в административной панели SendGrid зайдите в меню Marketing в подменю senders и в правом верхнем углу нажмите кнопку "Create New Sender". Заполните необходимые поля в предложенной форме. Сохраните. Должен получится следующий как на картинке результат, только с вашим email: - -![sender](sender-not-verify.png) - -На указанный email должно прийти письмо верификации (проверьте спам если не видите письма). Кликните на ссылку в нем и завершите процесс. Результат должен изменится на: - -![sender](sender-verify.png) - -- Теперь необходимо создать API токен доступа. Выбираем меню "Email API", и подменю "Integration Guide". Здесь выбираем "Web API" - -![api-key](web-api.png) - -Дальше необходимо выбрать технологию Node.js - -![api-key](node.png) - -На третьем шаге даем имя нашему токену. Например systemcats, нажимаем кнопку сгенерировать и получаем результат как на скриншоте ниже. Необходимо скопировать этот токен (это важно, так как больше вы не сможете его посмотреть). После завершить процесс создания токена - -![api-key](api-key.png) - -- Полученный API-токен надо добавить в `.env` файл в нашем проекте - -## Шаг 2 - -### Создание ендпоинта для верификации email'а - -- добавить в модель `User` два поля `verificationToken` и `verify`. Значение поля `verify` равное `false` будет означать, что его email еще не прошел верификацию - -```js -{ - verify: { - type: Boolean, - default: false, - }, - verificationToken: { - type: String, - required: [true, 'Verify token is required'], - }, -} -``` - -- создать эндпоинт GET [`/users/verify/:verificationToken`](#verification-request), где по параметру `verificationToken` мы будем искать пользователя в модели `User` -- если пользователь с таким токеном не найден, необходимо вернуть [Ошибку 'Not Found'](#verification-user-not-found) -- если пользователь найден - устанавливаем `verificationToken` в `null`, а поле `verify` ставим равным `true` в документе пользователя и возвращаем [Успешный ответ](#verification-success-response) - -### Verification request - -```shell -GET /users/verify/:verificationToken -``` - -### Verification user Not Found - -```shell -Status: 404 Not Found -ResponseBody: { - message: 'User not found' -} -``` - -### Verification success response - -```shell -Status: 200 OK -ResponseBody: { - message: 'Verification successful', -} -``` - -## Шаг 3 - -### Добавление отправки email пользователю с ссылкой для верификации - -При создания пользователя при регистрации: - -- создать `verificationToken` для пользователя и записать его в БД (для генерации токена используйте пакет [uuid](https://www.npmjs.com/package/uuid) или [nanoid](https://www.npmjs.com/package/nanoid)) -- отправить email на почту пользователя и указать ссылку для верификации email'а (`/users/verify/:verificationToken`) в сообщении -- Так же необходимо учитывать, что теперь логин пользователя не разрешен при не верифицированном email - -## Шаг 4 - -### Добавление повторной отправки email пользователю с ссылкой для верификации - -Необходимо предусмотреть, вариант, что пользователь может случайно удалить письмо. Оно может не дойти по какой-то причине к адресату. Наш сервис отправки писем во время регистрации выдал ошибку и т.д. - -#### @ POST /users/verify/ - -- Получает `body` в формате `{ email }` -- Если в `body` нет обязательного поля `email`, возвращает json с ключом `{"message": "missing required field email"}` и статусом `400` -- Если с `body` все хорошо, выполняем повторную отправку письма с `verificationToken` на указанный email, но только если пользователь не верифицирован -- Если пользователь уже прошел верификацию отправить json с ключом `{ message: "Verification has already been passed"}` со статусом `400 Bad Request` - -#### Resending a email request - -```shell -POST /users/verify -Content-Type: application/json -RequestBody: { - "email": "example@example.com" -} -``` - -#### Resending a email validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Ошибка от Joi или другой библиотеки валидации> -``` - -#### Resending a email success response - -```shell -Status: 200 Ok -Content-Type: application/json -ResponseBody: { - "message": "Verification email sent" -} -``` - -#### Resend email for verified user - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: { - message: "Verification has already been passed" -} -``` - -> Примечание: Как альтернативу SendGrid можно использовать пакет [nodemailer](https://www.npmjs.com/package/nodemailer) - -## Дополнительное задание - необязательное - -### 1. Напишите dockerfile для вашего приложения - +## GoIT Node.js Course Template Homework diff --git a/homework-06/README.pl.md b/homework-06/README.pl.md deleted file mode 100644 index 77000ca..0000000 --- a/homework-06/README.pl.md +++ /dev/null @@ -1,155 +0,0 @@ -**Czytaj w innych językach: [rosyjski](README.md), [ukraiński](README.ua.md).** - -# Zadanie domowe 6 - -Utwórz gałąź `hw06-email` z gałęzi `master`. - -Kontynuujemy tworzenie REST API pracy ze zbiorem kontaktów. Dodaj weryfikację emaila użytkownika po rejestracji przy pomocy serwisu [SendGrid](https://sendgrid.com/). - -## Jak powinien działać proces weryfikacji - -1. Po rejestracji użytkownik powinien otrzymać wiadomość na wskazaną przy rejestracji pocztę z odnośnikiem do weryfikacji swojego emaila. -2. Przechodząc do odnośnika w otrzymanej wiadomości po raz pierwszy, użytkownik powinien otrzymać [Odpowiedź ze statusem 200](#verification-success-response), co będzie oznaczać pomyślną weryfikację emaila. -3. Przechodząc po odnośniku powtórnie użytkownik powinien otrzymać [Błąd ze statusem 404](#verification-user-not-found). - -## Krok 1 - -### Przygotowanie integracji z SendGrid API - -- Zarejestruj się na [SendGrid](https://sendgrid.com/). -- Utwórz email nadawcy. W tym celu w panelu administratora SendGrid przejdź do menu Marketing w podmenu senders i w prawym górnym rogu wciśnij przycisk "Create New Sender". Uzupełnij wymagane pola w dołączonym formularzu. Zapisz. Rezultat powinien wyglądać jak na obrazku, tylko z twoim adresem email: - -![sender](sender-not-verify.png) - -Na wskazany email powinna przyjść wiadomość weryfikacyjna (sprawdź spam, jeśli nie widzisz wiadomości). Kliknij na odnośnik w niej i zakończ proces. Wynik powinien zmienić się na: - -![sender](sender-verify.png) - -- Teraz należy utworzyć API token dostępu. Wybieramy menu "Email API" i podmenu "Integration Guide". Tutaj wybieramy "Web API". - -![api-key](web-api.png) - -Dalej należy wybrać technologię Node.js. - -![api-key](node.png) - -W trzecim kroku nazywamy nasz token, na przykład systemcats. Klikamy na przycisk "wygeneruj" i otrzymujemy wynik jak na zrzucie ekranu niżej. Należy skopiować ten token (to ważne, ponieważ więcej nie możesz go zobaczyć). Następnie zakończ proces tworzenia tokena. - -![api-key](api-key.png) - -- Otrzymany token API należy dodać do pliku `.env` w naszym projekcie. - -## Krok 2 - -### Utworzenie endpointu dla weryfikacji emaila - -- Dodaj do modelu `User` dwa pola `verificationToken` i `verify`. Wartość pola `verify` równa `false` będzie oznaczać, że email jeszcze nie przeszedł weryfikacji. - -```js -{ - verify: { - type: Boolean, - default: false, - }, - verificationToken: { - type: String, - required: [true, 'Verify token is required'], - }, -} -``` - -- Utwórz endpoint GET [`/users/verify/:verificationToken`](#verification-request), gdzie w parametrze `verificationToken` będziemy szukać użytkownika w modelu `User`; -- jeśli użytkownik z takim tokenem nie zostanie znaleziony, należy zwrócić [Błąd 'Not Found'](#verification-user-not-found); -- jeśli użytkownik został odnaleziony – ustawiamy `verificationToken` na `null`, a pole `verify` ustawiamy jako równe `true` w dokumencie użytkownika zwracamy [Sukces odpowiedzi](#verification-success-response). - -### Verification request - -```shell -GET /users/verify/:verificationToken -``` - -### Verification user Not Found - -```shell -Status: 404 Not Found -ResponseBody: { - message: 'User not found' -} -``` - -### Verification success response - -```shell -Status: 200 OK -ResponseBody: { - message: 'Verification successful', -} -``` - -## Krok 3 - -### Dodanie wysłania emaila do użytkownika z odnośnikiem dla weryfikacji - -Podczas tworzenia użytkownika przy rejestracji: - -- utworzyć `verificationToken` dla użytkownika i zapisać go w bazie danych (do wygenerowania tokena wykorzystaj pakiet [uuid](https://www.npmjs.com/package/uuid) lub [nanoid](https://www.npmjs.com/package/nanoid)); -- wysłać email na pocztę użytkownika i wskazać odnośnik do weryfikacji emaila (`/users/verify/:verificationToken`) w wiadomości; -- należy wziąć pod uwagę, że teraz login użytkownika nie jest dozwolony przy nieweryfikowanym emailu. - -## Krok 4 - -### Dodanie powtórnego wysłania emaila do użytkownika z odnośnikiem dla weryfikacji - -Należy przewidzieć wariant, że użytkownik może po prostu usunąć wiadomość, z jakiejś przyczyna może ona nie dojść do adresata albo nasz serwis wysyłania wiadomości w czasie rejestracji wyświetlił błąd i tak dalej. - -#### @ POST /users/verify/ - -- Otrzymuje `body` w formacie `{ email }`. -- Jeśli w `body` nie ma obowiązkowego pola `email`, zwraca json z kluczem `{"message": "missing required field email"}` i statusem `400`. -- Jeśli z `body` wszystko w porządku, wykonujemy ponownie wysłanie wiadomości z `verificationToken` na wskazany email, ale tylko jeśli użytkownik nie został zweryfikowany. -- Jeżeli użytkownik przeszedł już weryfikację, wysłać json z kluczem `{ message: "Verification has already been passed"}` ze statusem `400 Bad Request`. - -#### Resending a email request - -```shell -POST /users/verify -Content-Type: application/json -RequestBody: { - "email": "example@example.com" -} -``` - -#### Resending a email validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: -``` - -#### Resending a email success response - -```shell -Status: 200 Ok -Content-Type: application/json -ResponseBody: { - "message": "Verification email sent" -} -``` - -#### Resend email for verified user - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: { - message: "Verification has already been passed" -} -``` - -> Uwaga: Jako alternatywę SendGrid można wykorzystać pakiet [nodemailer](https://www.npmjs.com/package/nodemailer). - -## Zadanie dodatkowe – nieobowiązkowe - -### 1. Napisz dockerfile dla twojej aplikacji - diff --git a/homework-06/README.ua.md b/homework-06/README.ua.md deleted file mode 100755 index f659031..0000000 --- a/homework-06/README.ua.md +++ /dev/null @@ -1,154 +0,0 @@ -**Читати на інших мовах: [Русский](README.md), [Українська](README.ua.md).** - -# Домашнє завдання 6 - -Створи гілку `hw06-email` з гілки` master`. - -Продовжуємо створення REST API для роботи з колекцією контактів. Додайте верифікацію email користувача після реєстрації за допомогою сервісу [SendGrid](https://sendgrid.com/). - -## Як процес верифікації повинен працювати - -1. Після реєстрації, користувач повинен отримати лист на вказану при реєстрації пошту з посиланням для верифікації свого email -2. Пройшовши по посиланню в отриманому листі, в перший раз, користувач повинен отримати [Відповідь зі статусом 200](#verification-success-response), що буде мати на увазі успішну верифікацію email -3. Пройшовши по посиланню повторно користувач повинен отримати [Помилку зі статусом 404](#verification-user-not-found) - -## Крок 1 - -### Підготовка інтеграції з SendGrid API - -- Зареєструйся на [SendGrid](https://sendgrid.com/). -- Створи email-відправника. Для цього в адміністративній панелі SendGrid зайдіть в меню Marketing в підменю senders і в правому верхньому куті натисніть кнопку "Create New Sender". Заповніть поля в запропонованій формі. Збережіть. Повинен вийти наступний, як на картинці, результат, тільки з вашим email: - -![Sender](sender-not-verify.png) - -На вказаний email має прийти лист верифікації (перевірте спам якщо не бачите листи). Натисніть на посилання в ньому і завершіть процес. Результат повинен зміниться на: - -![Sender](sender-verify.png) - -- Тепер необхідно створити API токен доступу. Вибираємо меню "Email API", і підменю "Integration Guide". Тут вибираємо "Web API" - -![Api-key](web-api.png) - -Далі необхідно вибрати технологію Node.js - -![Api-key](node.png) - -На третьому кроці даємо ім'я нашого токену. Наприклад, systemcats, натискаємо кнопку згенерувати і отримуємо результат як на скріншоті нижче. Необхідно скопіювати цей токен (це важливо, тому що більше ви не зможете його подивитися). Після цього завершити процес створення токена - -![Api-key](api-key.png) - -- Отриманий API-токен треба додати в `.env` файл в нашому проекті - -## Крок 2 - -### Створення ендпоінта для верифікації email - -- додати в модель `User` два поля `verificationToken` і `verify`. Значення поля `verify` рівне `false` означатиме, що його email ще не пройшов верифікацію - -```js -{ - verify: { - type: Boolean, - default: false, - }, - verificationToken: { - type: String, - required: [true, 'Verify token is required'], - }, -} -``` - -- створити ендпоінт GET [`/users/verify/:verificationToken`](# verification-request), де по параметру `verificationToken` ми будемо шукати користувача в моделі `User` -- якщо користувач з таким токеном не знайдений, необхідно повернути [Помилку 'Not Found'](#verification-user-not-found) -- якщо користувач знайдений - встановлюємо `verificationToken` в `null`, а поле `verify` ставимо рівним `true` в документі користувача і повертаємо [Успішну відповідь](#verification-success-response) - -### Verification request - -```shell -GET /users/verify/:verificationToken -``` - -### Verification user Not Found - -```shell -Status: 404 Not Found -ResponseBody: { - message: 'User not found' -} -``` - -### Verification success response - -```shell -Status: 200 OK -ResponseBody: { - message: 'Verification successful', -} -``` - -## Крок 3 - -### Додавання відправки email користувачу з посиланням для верифікації - -При створенні користувача при реєстрації: - -- створити `verificationToken` для користувача і записати його у БД (для генерації токена використовуйте пакет [uuid](https://www.npmjs.com/package/uuid) або [nanoid](https://www.npmjs.com/package/nanoid)) -- відправити email на пошту користувача і вказати посилання для верифікації email'а ( `/users/verify/:verificationToken`) в повідомленні -- Так само необхідно враховувати, що тепер логін користувача не дозволений, якщо не верифікувано email - -## Крок 4 - -### Додавання повторної відправки email користувачу з посиланням для верифікації - -Необхідно передбачити, варіант, що користувач може випадково видалити лист. Воно може не дійти з якоїсь причини до адресата. Наш сервіс відправки листів під час реєстрації видав помилку і т.д. - -#### @ POST /users/verify - -- Отримує `body` у форматі `{email}` -- Якщо в `body` немає обов'язкового поля `email`, повертає json з ключем `{"message":"missing required field email"}` і статусом `400` -- Якщо з `body` все добре, виконуємо повторну відправку листа з `verificationToken` на вказаний email, але тільки якщо користувач не верифікований -- Якщо користувач вже пройшов верифікацію відправити json з ключем `{"message":"Verification has already been passed"}` зі статусом `400 Bad Request` - -#### Resending a email request - -````shell -POST /users/verify -Content-Type: application/json -RequestBody: { - "email": "example@example.com" -} -`` ` - -#### Resending a email validation error - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: <Помилка від Joi або іншої бібліотеки валідації> -```` - -#### Resending a email success response - -```shell -Status: 200 Ok -Content-Type: application/json -ResponseBody: { - "message": "Verification email sent" -} -``` - -#### Resend email for verified user - -```shell -Status: 400 Bad Request -Content-Type: application/json -ResponseBody: { - message: "Verification has already been passed" -} -``` - -> Примітка: Як альтернативу SendGrid можна використовувати пакет [nodemailer](https://www.npmjs.com/package/nodemailer) - -## Додаткове завдання - необов'язкове - -### 1. Напишіть dockerfile для вашої програми diff --git a/homework-06/controllers/auth/changeSubscription.js b/homework-06/controllers/auth/changeSubscription.js new file mode 100644 index 0000000..7fa746c --- /dev/null +++ b/homework-06/controllers/auth/changeSubscription.js @@ -0,0 +1,13 @@ +const { User } = require("../../models/user"); + +const changeSubscription = async (req, res) => { + const { _id } = req.user; + const { subscription } = req.body; + await User.findByIdAndUpdate(_id, { subscription }); + + res.json({ + message: `Your subscription has been changed to ${subscription}`, + }); +}; + +module.exports = changeSubscription; diff --git a/homework-06/controllers/auth/getCurrent.js b/homework-06/controllers/auth/getCurrent.js new file mode 100644 index 0000000..8612179 --- /dev/null +++ b/homework-06/controllers/auth/getCurrent.js @@ -0,0 +1,11 @@ +const getCurrent = async (req, res) => { + const { name, email, subscription } = req.user; + + res.json({ + name, + email, + subscription, + }); +}; + +module.exports = getCurrent; diff --git a/homework-06/controllers/auth/index.js b/homework-06/controllers/auth/index.js new file mode 100644 index 0000000..61b3b6d --- /dev/null +++ b/homework-06/controllers/auth/index.js @@ -0,0 +1,19 @@ +const register = require("./register"); +const login = require("./login"); +const logout = require("./logout"); +const getCurrent = require("./getCurrent"); +const changeSubscription = require("./changeSubscription"); +const updateAvatar = require("./updateAvatar"); +const resendVerifyEmail = require("./resendVerifyEmail"); +const verifyEmail = require("./verifyEmail"); + +module.exports = { + register, + login, + logout, + getCurrent, + changeSubscription, + updateAvatar, + resendVerifyEmail, + verifyEmail, +}; diff --git a/homework-06/controllers/auth/login.js b/homework-06/controllers/auth/login.js new file mode 100644 index 0000000..24b7db0 --- /dev/null +++ b/homework-06/controllers/auth/login.js @@ -0,0 +1,40 @@ +const bcryptjs = require('bcryptjs'); // Підключення бібліотеки для хешування паролів +const jwt = require('jsonwebtoken'); +const { User } = require('../../models/user'); +const { HttpError } = require('../../helpers'); +const { SECRET_KEY } = process.env; + +const login = async (req, res) => { + const { email, password } = req.body; + const user = await User.findOne({ email }); + + if (!user) { + throw HttpError(401, 'Email or password is wrong'); + } + + if (!user.verify) { + throw HttpError(401, 'Email not verified'); + } + + const passwordCompare = await bcryptjs.compare(password, user.password); // Перевірка, чи введений пароль збігається з хешованим паролем користувача + if (!passwordCompare) { + throw HttpError(401, 'Email or password is wrong'); + } + + const payload = { + id: user._id, + }; // Створення об'єкту payload для підпису в JWT токені + + const token = jwt.sign(payload, SECRET_KEY, { expiresIn: '7d' }); // Створення JWT токена з підписом на основі payload та секретного ключа + await User.findByIdAndUpdate(user._id, { token }); // Збереження JWT токена в базі даних + + res.json({ + token, + user: { + email: user.email, + subscription: user.subscription, + }, + }); // Відправлення відповіді з JWT токеном та даними користувача (email та підписка) +}; + +module.exports = login; diff --git a/homework-06/controllers/auth/logout.js b/homework-06/controllers/auth/logout.js new file mode 100644 index 0000000..9b33d95 --- /dev/null +++ b/homework-06/controllers/auth/logout.js @@ -0,0 +1,10 @@ +const { User } = require("../../models/user"); + +const logout = async (req, res) => { + const { _id } = req.user; + await User.findByIdAndUpdate(_id, { token: "" }); + + res.status(204).json(); +}; + +module.exports = logout; diff --git a/homework-06/controllers/auth/register.js b/homework-06/controllers/auth/register.js new file mode 100644 index 0000000..275efd2 --- /dev/null +++ b/homework-06/controllers/auth/register.js @@ -0,0 +1,44 @@ +const bcryptjs = require('bcryptjs'); // Підключення бібліотеки для хешування паролів +const gravatar = require('gravatar'); // Підключення бібліотеки для отримання аватарки з сервісу Gravatar +const { User } = require('../../models/user'); +const { HttpError, sendEmail } = require('../../helpers'); +const { nanoid } = require('nanoid'); +require('dotenv').config(); + +const { BASE_URL } = process.env; + +const register = async (req, res) => { + const { email, password } = req.body; + const user = await User.findOne({ email }); // Знаходження користувача за email в базі даних (звернення до бази даних потребує await, щоб дочекатись результату пошуку) + + if (user) { + throw HttpError(409, 'Email in use'); + } + + const hashPassword = await bcryptjs.hash(password, 10); // Хешування пароля з використанням bcryptjs + const avatarUrl = gravatar.url(email); // Отримання посилання на аватарку з сервісу Gravatar + const verificationToken = nanoid(); + + const newUser = await User.create({ + ...req.body, + password: hashPassword, + avatarUrl, + verificationToken, + }); + + const verifyEmail = { + to: email, + subject: 'Verify email', + html: `Click to verify email`, + }; // Створення об'єкту email для відправки листа з посиланням для верифікації email + + await sendEmail(verifyEmail); // Відправлення листа з посиланням на верифікацію email + + res.status(201).json({ + name: newUser.name, + email: newUser.email, + avatar: newUser.avatarUrl, + }); // Відправлення відповіді з даними про створеного користувача +}; + +module.exports = register; diff --git a/homework-06/controllers/auth/resendVerifyEmail.js b/homework-06/controllers/auth/resendVerifyEmail.js new file mode 100644 index 0000000..2228baa --- /dev/null +++ b/homework-06/controllers/auth/resendVerifyEmail.js @@ -0,0 +1,31 @@ +const { User } = require('../../models/user'); +const { HttpError, sendEmail } = require('../../helpers'); +require('dotenv').config(); +const { BASE_URL } = process.env; + +const resendVerifyEmail = async (req, res) => { + const { email } = req.body; + const user = await User.findOne({ email }); + + if (!user) { + throw HttpError(401, 'User not found'); + } + + if (user.verify) { + throw HttpError(400, 'Verification has already been passed'); + } + + const verifyEmail = { + to: email, + subject: 'Verify email', + html: `Click to verify email`, + }; // Створення об'єкту email для відправки листа з посиланням для верифікації email + + await sendEmail(verifyEmail); // Відправлення листа з посиланням на верифікацію email + + res.json({ + message: 'Verification email sent', + }); // Відправлення відповіді з підтвердженням відправки листа +}; + +module.exports = resendVerifyEmail; diff --git a/homework-06/controllers/auth/updateAvatar.js b/homework-06/controllers/auth/updateAvatar.js new file mode 100644 index 0000000..c545726 --- /dev/null +++ b/homework-06/controllers/auth/updateAvatar.js @@ -0,0 +1,43 @@ +const { User } = require('../../models/user'); +const path = require('path'); +const fs = require('fs/promises'); +const { HttpError, resizeImage } = require('../../helpers'); +const avatarsDir = path.join(__dirname, '../../public/avatars'); +const tempDir = path.join(__dirname, '../../temp'); +const avatarExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff']; + +const updateAvatar = async (req, res) => { + const { _id } = req.user; + const { path: tempUpload, originalname } = req.file; + const avatarName = `${_id}_${originalname}`; + + const fileExtension = originalname.substring(originalname.lastIndexOf('.') + 1); + + if (!avatarExtensions.includes(fileExtension.toLowerCase())) { + // Перевірка, чи допустиме розширення файлу + throw new HttpError( + 400, + `${originalname} includes an invalid file extension! Must be: ${avatarExtensions.join(', or ')}`, + ); + } + + const tempImagePath = path.join(tempDir, avatarName); + const resizedImagePath = path.join(avatarsDir, avatarName); + + try { + await fs.stat(tempImagePath); // Перевірка, чи існує тимчасовий файл з аватаркою + } catch (error) { + await fs.copyFile(tempUpload, tempImagePath); // Копіювання завантаженого тимчасового файлу в папку temp, якщо файлу ще немає + } + + await resizeImage(tempImagePath, resizedImagePath); + + const avatarURL = path.join('avatars', avatarName); // Формування шляху до аватарки для збереження в базу даних + await User.findByIdAndUpdate(_id, { avatarURL }); // Оновлення запису користувача з новим посиланням на аватарку + + res.json({ + avatarURL, + }); +}; + +module.exports = updateAvatar; diff --git a/homework-06/controllers/auth/verifyEmail.js b/homework-06/controllers/auth/verifyEmail.js new file mode 100644 index 0000000..9c72488 --- /dev/null +++ b/homework-06/controllers/auth/verifyEmail.js @@ -0,0 +1,22 @@ +const { User } = require("../../models/user"); +const { HttpError } = require("../../helpers"); + +const verifyEmail = async (req, res) => { + const { verificationToken } = req.params; + const user = await User.findOne({ verificationToken }); + + if (!user) { + throw HttpError(401, "User Not found"); + } + + await User.findByIdAndUpdate(user._id, { + verify: true, + verificationToken: "", + }); + + res.json({ + message: "Verification successful", + }); +}; + +module.exports = verifyEmail; diff --git a/homework-06/controllers/contacts/addContact.js b/homework-06/controllers/contacts/addContact.js new file mode 100644 index 0000000..6b38b95 --- /dev/null +++ b/homework-06/controllers/contacts/addContact.js @@ -0,0 +1,17 @@ +const { Contact, addSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const addContact = async (req, res) => { + const { error } = addSchema.validate(req.body); + + if (error) { + throw HttpError(400, 'missing required name field'); + } + + const { _id: owner } = req.user; + const result = await Contact.create({ ...req.body, owner }); + + res.status(201).json(result); +}; + +module.exports = addContact; diff --git a/homework-06/controllers/contacts/getById.js b/homework-06/controllers/contacts/getById.js new file mode 100644 index 0000000..3c46b85 --- /dev/null +++ b/homework-06/controllers/contacts/getById.js @@ -0,0 +1,13 @@ +const { Contact } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const getById = async (req, res) => { + const { id } = req.params; + const result = await Contact.findById(id); + if (!result) { + throw HttpError(404, 'Not found'); + } + res.json(result); +}; + +module.exports = getById; diff --git a/homework-06/controllers/contacts/index.js b/homework-06/controllers/contacts/index.js new file mode 100644 index 0000000..126f94b --- /dev/null +++ b/homework-06/controllers/contacts/index.js @@ -0,0 +1,15 @@ +const listContacts = require("./listContacts"); +const getById = require("./getById"); +const addContact = require("./addContact"); +const updateById = require("./updateById"); +const updateStatusContact = require("./updateStatusContact"); +const removeContact = require("./removeContact"); + +module.exports = { + listContacts, + getById, + addContact, + updateById, + updateStatusContact, + removeContact, +}; diff --git a/homework-06/controllers/contacts/listContacts.js b/homework-06/controllers/contacts/listContacts.js new file mode 100644 index 0000000..ac9272f --- /dev/null +++ b/homework-06/controllers/contacts/listContacts.js @@ -0,0 +1,22 @@ +const { Contact } = require('../../models/contact'); + +const listContacts = async (req, res) => { + const { _id: owner } = req.user; + const { page = 1, limit = 10 } = req.query; // Отримуємо номер сторінки (page) та кількість контактів на сторінці (limit) з параметрів запиту + const skip = (page - 1) * limit; // Обчислюємо кількість контактів, які необхідно пропустити перед отриманням даних з бази даних + + if (req.query.favorite) { + const favorite = req.query.favorite === 'true'; // Конвертуємо параметр favorite в булеве значення + const result = await Contact.find({ owner, favorite }, '', { + // Знаходимо контакти в базі даних, де owner дорівнює id користувача і favorite дорівнює переданому значенню + skip, + limit, + }).populate('owner', 'name email'); + return res.json(result); + } + + const result = await Contact.find({ owner }, '', { skip, limit }).populate('owner', 'name email'); // Знаходимо всі контакти, де owner дорівнює id користувача, з врахуванням пагінації + res.json(result); +}; + +module.exports = listContacts; diff --git a/homework-06/controllers/contacts/removeContact.js b/homework-06/controllers/contacts/removeContact.js new file mode 100644 index 0000000..ec1b303 --- /dev/null +++ b/homework-06/controllers/contacts/removeContact.js @@ -0,0 +1,17 @@ +const { Contact } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const removeContact = async (req, res) => { + const { id } = req.params; + const result = await Contact.findByIdAndDelete(id); + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json({ + message: 'contact deleted', // Відправляємо відповідь у форматі JSON з повідомленням про успішне видалення контакта + }); +}; + +module.exports = removeContact; \ No newline at end of file diff --git a/homework-06/controllers/contacts/updateById.js b/homework-06/controllers/contacts/updateById.js new file mode 100644 index 0000000..c7a63ea --- /dev/null +++ b/homework-06/controllers/contacts/updateById.js @@ -0,0 +1,21 @@ +const { Contact, addSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const updateById = async (req, res) => { + const { error } = addSchema.validate(req.body); // Перевіряємо, чи дані відповідають схемі addSchema + + if (error) { + throw HttpError(400, 'missing fields'); + } + + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); // Знаходимо контакт за id та оновлюємо його дані на ті, що були передані у запиті + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateById; diff --git a/homework-06/controllers/contacts/updateStatusContact.js b/homework-06/controllers/contacts/updateStatusContact.js new file mode 100644 index 0000000..c4534ef --- /dev/null +++ b/homework-06/controllers/contacts/updateStatusContact.js @@ -0,0 +1,21 @@ +const { Contact, updateFavoriteSchema } = require('../../models/contact'); +const { HttpError } = require('../../helpers'); + +const updateStatusContact = async (req, res) => { + const { error } = updateFavoriteSchema.validate(req.body); // Перевіряємо, чи дані з введеним полем favorite відповідають схемі updateFavoriteSchema + + if (error) { + throw HttpError(400, 'missing field favorite'); + } + + const { id } = req.params; + const result = await Contact.findByIdAndUpdate(id, req.body, { new: true }); // Знаходимо контакт за id та оновлюємо його дані на ті, що були передані у запиті + + if (!result) { + throw HttpError(404, 'Not found'); + } + + res.json(result); +}; + +module.exports = updateStatusContact; diff --git a/homework-06/helpers/HttpError.js b/homework-06/helpers/HttpError.js new file mode 100644 index 0000000..3f38b50 --- /dev/null +++ b/homework-06/helpers/HttpError.js @@ -0,0 +1,7 @@ +const HttpError = (status, message) => { + const error = new Error(message); + error.status = status; + return error; +}; + +module.exports = HttpError; diff --git a/homework-06/helpers/ctrlWrapper.js b/homework-06/helpers/ctrlWrapper.js new file mode 100644 index 0000000..4e36751 --- /dev/null +++ b/homework-06/helpers/ctrlWrapper.js @@ -0,0 +1,13 @@ +const ctrlWrapper = ctrl => { + const func = async (req, res, next) => { + try { + await ctrl(req, res, next); + } catch (error) { + next(error); + } + }; + + return func; +}; + +module.exports = ctrlWrapper; diff --git a/homework-06/helpers/handleMongooseError.js b/homework-06/helpers/handleMongooseError.js new file mode 100644 index 0000000..f98813b --- /dev/null +++ b/homework-06/helpers/handleMongooseError.js @@ -0,0 +1,8 @@ +const handleMongooseError = (error, data, next) => { + const { name, code } = error; + const status = name === 'MongoServerError' && code === 11000 ? 409 : 400; + error.status = status; + next(); +}; + +module.exports = handleMongooseError; diff --git a/homework-06/helpers/index.js b/homework-06/helpers/index.js new file mode 100644 index 0000000..1a0dd31 --- /dev/null +++ b/homework-06/helpers/index.js @@ -0,0 +1,13 @@ +const HttpError = require("./HttpError"); +const ctrlWrapper = require("./ctrlWrapper"); +const handleMongooseError = require("./handleMongooseError"); +const resizeImage = require("./resizeImage"); +const sendEmail = require("./sendEmail"); + +module.exports = { + HttpError, + ctrlWrapper, + handleMongooseError, + resizeImage, + sendEmail, +}; diff --git a/homework-06/helpers/resizeImage.js b/homework-06/helpers/resizeImage.js new file mode 100644 index 0000000..099db71 --- /dev/null +++ b/homework-06/helpers/resizeImage.js @@ -0,0 +1,9 @@ +const Jimp = require('jimp'); // Підключаємо бібліотеку Jimp для роботи з зображеннями + +const resizeImage = async (sourcePath, destinationPath) => { + const image = await Jimp.read(sourcePath); + image.resize(250, 250); + await image.writeAsync(destinationPath); // Зберігаємо зображення у вказаному шляху (destinationPath) за допомогою методу writeAsync() +}; + +module.exports = resizeImage; diff --git a/homework-06/helpers/sendEmail.js b/homework-06/helpers/sendEmail.js new file mode 100644 index 0000000..5eafcf1 --- /dev/null +++ b/homework-06/helpers/sendEmail.js @@ -0,0 +1,14 @@ +const sgMail = require('@sendgrid/mail'); // Підключаємо бібліотеку sendgrid/mail для надсилання електронних листів +require('dotenv').config(); // Підключаємо .env для отримання SENDGRID_API_KEY + +const { SENDGRID_API_KEY } = process.env; // Отримуємо SENDGRID_API_KEY з оточення + +sgMail.setApiKey(SENDGRID_API_KEY); + +const sendEmail = async data => { + const email = { ...data, from: 'supermetamail@meta.ua' }; + await sgMail.send(email); + return true; // Після успішного надсилання повертаємо значення true +}; + +module.exports = sendEmail; diff --git a/homework-06/middlewares/authenticate.js b/homework-06/middlewares/authenticate.js new file mode 100644 index 0000000..92acdd6 --- /dev/null +++ b/homework-06/middlewares/authenticate.js @@ -0,0 +1,33 @@ +const jwt = require('jsonwebtoken'); +const { User } = require('../models/user'); + +require('dotenv').config(); // Підключаємо .env для отримання SECRET_KEY +const { SECRET_KEY } = process.env; + +const { HttpError } = require('../helpers'); + +const authenticate = async (req, res, next) => { + const { authorization = '' } = req.headers; // Отримуємо заголовок Authorization з запиту, який містить токен доступу + const [bearer, token] = authorization.split(' '); // Розбиваємо заголовок Authorization на дві частини: тип токена та сам токен + + if (bearer !== 'Bearer') { + next(HttpError(401, 'Not authorized')); + } + + try { + const { id } = jwt.verify(token, SECRET_KEY); + const user = await User.findById(id); + + if (!user || !user.token || user.token !== token) { + next(HttpError(401, 'Not authorized')); + } + + req.user = user; + + next(); // Переходимо до наступної мідлвари або обробника запиту + } catch { + next(HttpError(401, 'Not authorized')); + } +}; + +module.exports = authenticate; diff --git a/homework-06/middlewares/index.js b/homework-06/middlewares/index.js new file mode 100644 index 0000000..52b70c5 --- /dev/null +++ b/homework-06/middlewares/index.js @@ -0,0 +1,5 @@ +const isValidId = require("./isValidId"); +const authenticate = require("./authenticate"); +const validateBody = require("./validateBody"); +const upload = require("./upload"); +module.exports = { isValidId, authenticate, validateBody, upload }; diff --git a/homework-06/middlewares/isValidId.js b/homework-06/middlewares/isValidId.js new file mode 100644 index 0000000..b2bf179 --- /dev/null +++ b/homework-06/middlewares/isValidId.js @@ -0,0 +1,14 @@ +const { isValidObjectId } = require('mongoose'); +const { HttpError } = require('../helpers'); + +const isValidId = (req, res, next) => { + const { id } = req.params; + if (!isValidObjectId(id)) { + // Перевіряємо чи переданий ідентифікатор є дійсним ObjectId + next(HttpError(400, `${id} is not valid id`)); + } + + next(); // Якщо ідентифікатор є дійсним ObjectId, переходимо до наступної мідлвари або обробника запиту +}; + +module.exports = isValidId; diff --git a/homework-06/middlewares/upload.js b/homework-06/middlewares/upload.js new file mode 100644 index 0000000..bdd49ce --- /dev/null +++ b/homework-06/middlewares/upload.js @@ -0,0 +1,17 @@ +const multer = require('multer'); // Підключаємо бібліотеку multer для обробки завантаження файлів +const path = require('path'); + +const tempDir = path.join(__dirname, '../', 'temp'); + +const multerConfig = multer.diskStorage({ + destination: tempDir, // Вказуємо директорію, куди будуть збережені тимчасові завантажені файли + filename: (req, file, cb) => { + cb(null, file.originalname); // Генеруємо ім'я файлу на основі його оригінального імені + }, +}); + +const upload = multer({ + storage: multerConfig, // Передаємо конфігурацію multer для завантаження файлів +}); + +module.exports = upload; diff --git a/homework-06/middlewares/validateBody.js b/homework-06/middlewares/validateBody.js new file mode 100644 index 0000000..70bcdd2 --- /dev/null +++ b/homework-06/middlewares/validateBody.js @@ -0,0 +1,15 @@ +const { HttpError } = require('../helpers'); + +// Мідлвар для перевірки валідності даних в запиті на відповідну схему "schema" +const validateBody = schema => { + const func = (req, res, next) => { + const { error } = schema.validate(req.body); + if (error) { + next(HttpError(400, error.message)); + } + next(); // Якщо дані валідні, передаємо управління наступному мідлвару або обробнику запиту + }; + return func; +}; + +module.exports = validateBody; diff --git a/homework-06/models/contact.js b/homework-06/models/contact.js new file mode 100644 index 0000000..ea91407 --- /dev/null +++ b/homework-06/models/contact.js @@ -0,0 +1,48 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const contactSchema = new Schema( + { + name: { + type: String, + required: [true, 'Set name for contact'], + }, + email: { + type: String, + }, + phone: { + type: String, + }, + favorite: { + type: Boolean, + default: false, + }, + owner: { + type: Schema.Types.ObjectId, + ref: 'user', + required: true, + }, + }, + { versionKey: false }, // Вимкнення версій документів (поле "__v") +); + +// Після збереження документа виникає помилка, обробка помилки зі спеціальною функцією +contactSchema.post('save', handleMongooseError); + +// Модель контакту зі схемою імені "contact" +const Contact = model('contact', contactSchema); + +// Схема валідації даних для додавання контакту +const addSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().required(), + phone: Joi.string().required(), +}); + +// Схема валідації даних для оновлення поля "favorite" контакту +const updateFavoriteSchema = Joi.object({ + favorite: Joi.boolean().required(), +}); + +module.exports = { Contact, addSchema, updateFavoriteSchema }; diff --git a/homework-06/models/user.js b/homework-06/models/user.js new file mode 100644 index 0000000..89249f2 --- /dev/null +++ b/homework-06/models/user.js @@ -0,0 +1,89 @@ +const { Schema, model } = require('mongoose'); +const Joi = require('joi'); +const { handleMongooseError } = require('../helpers'); + +const emailRegexp = /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/; +const subscriptionList = ['starter', 'pro', 'business']; + +// Створення схеми користувача з використанням mongoose +const userSchema = new Schema( + { + name: { + type: String, + required: true, + }, + email: { + type: String, + match: emailRegexp, + required: [true, 'Email is required'], + unique: true, + }, + password: { + type: String, + minlength: 6, + required: [true, 'Set password for user'], + }, + subscription: { + type: String, + enum: subscriptionList, + default: 'starter', + }, + token: { + type: String, + default: '', // Значення за замовчуванням для токена + }, + avatarURL: { + type: String, + required: true, // Обов'язкове поле для посилання на аватар + }, + verify: { + type: Boolean, + default: false, // Значення за замовчуванням для підтвердження електронної пошти + }, + verificationToken: { + type: String, + required: [true, 'Verify token is required'], + }, + }, + { versionKey: false }, // Вимкнення версій документів (поле "__v") +); + +// Після збереження документа виникає помилка, обробка помилки зі спеціальною функцією +userSchema.post('save', handleMongooseError); + +// Об'єкт Joi схем для валідації даних +const registerSchema = Joi.object({ + name: Joi.string().required(), + email: Joi.string().pattern(emailRegexp).required(), + password: Joi.string().min(6).required(), +}); + +const emailSchema = Joi.object({ + email: Joi.string().pattern(emailRegexp).required(), +}); + +const loginSchema = Joi.object({ + email: Joi.string().required(), + password: Joi.string().min(6).required(), +}); + +const changeSubscriptionSchema = Joi.object({ + subscription: Joi.string() + .valid(...subscriptionList) + .required(), +}); + +// Модель користувача зі схемою імені "user" та заданими схемами валідації +const User = model('user', userSchema); + +const schemas = { + registerSchema, + loginSchema, + changeSubscriptionSchema, + emailSchema, +}; + +module.exports = { + User, + schemas, +}; diff --git a/homework-06/node.png b/homework-06/node.png deleted file mode 100644 index 43834631d01cda7492d7ab292cb0641f3f507ec1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35439 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 O{@+!^+3z6Y=>G!AvcYfw literal 0 HcmV?d00001 diff --git a/homework-06/public/avatars/64a581f17ab9d2f81652c536_avatar.jpg b/homework-06/public/avatars/64a581f17ab9d2f81652c536_avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..86e804f8e53c4cf437efd1e8bde57ae0b8bdad1b GIT binary patch literal 7676 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 O{@+!^+3z6Y=>G!AvcYfw literal 0 HcmV?d00001 diff --git a/homework-06/routes/api/auth.js b/homework-06/routes/api/auth.js new file mode 100644 index 0000000..b780700 --- /dev/null +++ b/homework-06/routes/api/auth.js @@ -0,0 +1,28 @@ +const express = require('express'); + +const { validateBody, authenticate, upload } = require('../../middlewares'); +const { schemas } = require('../../models/user'); + +const router = express.Router(); + +const ctrl = require('../../controllers/auth'); + +const { ctrlWrapper } = require('../../helpers'); + +router.post('/register', validateBody(schemas.registerSchema), ctrlWrapper(ctrl.register)); + +router.get('/verify/:verificationToken', ctrlWrapper(ctrl.verifyEmail)); + +router.post('/verify', validateBody(schemas.emailSchema), ctrlWrapper(ctrl.resendVerifyEmail)); + +router.post('/login', validateBody(schemas.loginSchema), ctrlWrapper(ctrl.login)); + +router.get('/current', authenticate, ctrlWrapper(ctrl.getCurrent)); + +router.post('/logout', authenticate, ctrlWrapper(ctrl.logout)); + +router.patch('/users/avatars', authenticate, upload.single('avatar'), ctrlWrapper(ctrl.updateAvatar)); + +router.patch('/', authenticate, validateBody(schemas.changeSubscriptionSchema), ctrlWrapper(ctrl.changeSubscription)); + +module.exports = router; diff --git a/homework-06/routes/api/contacts.js b/homework-06/routes/api/contacts.js new file mode 100644 index 0000000..935d6f2 --- /dev/null +++ b/homework-06/routes/api/contacts.js @@ -0,0 +1,23 @@ +const express = require('express'); + +const router = express.Router(); + +const ctrl = require('../../controllers/contacts'); // Підключення контролерів для обробки запитів + +const { ctrlWrapper } = require('../../helpers'); + +const { isValidId, authenticate } = require('../../middlewares'); // Підключення middleware для перевірки валідності id та аутентифікації + +router.get('/', authenticate, ctrlWrapper(ctrl.listContacts)); + +router.get('/:id', authenticate, isValidId, ctrlWrapper(ctrl.getById)); + +router.post('/', authenticate, ctrlWrapper(ctrl.addContact)); + +router.put('/:id', authenticate, isValidId, ctrlWrapper(ctrl.updateById)); + +router.patch('/:id/favorite', authenticate, isValidId, ctrlWrapper(ctrl.updateStatusContact)); + +router.delete('/:id', authenticate, isValidId, ctrlWrapper(ctrl.removeContact)); + +module.exports = router; diff --git a/homework-06/sender-not-verify.png b/homework-06/sender-not-verify.png deleted file mode 100644 index 98aea7940627cf4e26c63c9d4d9a76d21077f02c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 11936 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 IuiuOOUyHCYSO5S3 diff --git a/homework-06/server.js b/homework-06/server.js new file mode 100644 index 0000000..1d43d4c --- /dev/null +++ b/homework-06/server.js @@ -0,0 +1,17 @@ +const mongoose = require('mongoose'); +const app = require('./app'); // Підключення Express-додатку з файлу `app.js` +const { DB_HOST } = process.env; + +// Встановлення з'єднання з базою даних MongoDB +mongoose + .connect(DB_HOST) + .then(() => { + console.log('Database connection successful'); + app.listen(3000, () => { + console.log('Server running. Use our API on port: 3000'); + }); + }) + .catch(error => { + console.log(error.message); + process.exit(1); // Вихід з процесу з кодом помилки 1, щоб позначити, що виникла помилка при підключенні + }); diff --git a/homework-06/temp/.gitkeep b/homework-06/temp/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/homework-06/temp/649c7f75733d3ba6bb281c92_avatar.jpg b/homework-06/temp/649c7f75733d3ba6bb281c92_avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef6fac6f54103589bf648cdb4b20894a50b25f4d GIT binary patch literal 43425 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 literal 0 HcmV?d00001 diff --git a/homework-06/temp/64a581f17ab9d2f81652c536_avatar.jpg b/homework-06/temp/64a581f17ab9d2f81652c536_avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef6fac6f54103589bf648cdb4b20894a50b25f4d GIT binary patch literal 43425 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 literal 0 HcmV?d00001 diff --git a/homework-06/temp/avatar.jpg b/homework-06/temp/avatar.jpg new file mode 100644 index 0000000000000000000000000000000000000000..ef6fac6f54103589bf648cdb4b20894a50b25f4d GIT binary patch literal 43425 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 literal 0 HcmV?d00001 diff --git a/homework-06/web-api.png b/homework-06/web-api.png deleted file mode 100644 index 6c4fe390ed99c6c2795a1c0b29e1255c0ee69624..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 35520 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