Теперь, когда мы настроили наш Backend. Мы хотим добавить еще пару вещей. Мы хотим иметь возможность сохранять данные в базе данных, а также извлекать информацию по запросу.

Предпосылки:

Нам нужно будет установить еще пару зависимостей в проект. Запустите следующее в терминале в корне папки проекта.

Использование НПМ:

npm i --save-dev mongoose bluebird connect-mongo express-session lodash

Использование пряжи:

yarn add --dev mongoose bluebird connect-mongo express-session lodash

mongoose — экспресс-подключение к базе данных MongoDB.

bluebird — библиотека, ориентированная на оптимальную отправку промисов

connect-mongo — промежуточное ПО для соединения узла и MongoDB.

express-session — создает экземпляры сеанса для экспресса и сохраняет в MongoDB.

lodash — избавление от хлопот при работе с массивами, числами, объектами, строками

Настройка файлов конфигурации сервера

До сих пор мы не использовали папку config. Эта папка должна содержать все файлы конфигурации для важных переменных на стороне сервера. Начнем с создания файла index.js в корне папки config.

Теперь мы можем использовать эти данные конфигурации для настройки подключения к MongoDB в файле app.js в корне папки Project.

Замените код в файле app.js. Как всегда, прочитайте комментарии, поскольку они объясняют, что все делает в файле app.js.

Теперь вы можете проверить это, запустив node app.js в своем терминале. Нам не нужно ng build, так как мы не изменили папку Frontend. Если вы войдете на свой сервер MongoDB, вы увидите новую коллекцию под названием sessions, которая содержит всю информацию о подключении нашего экспресс-сервера к базе данных MongoDB.

Настройка вашей первой конечной точки

Первой конечной точкой, которую мы хотим создать, всегда будет конечная точка пользователя. Эта пользовательская конечная точка будет отвечать за создание, сохранение и любые другие функции, которые нам нужны для нашей коллекции пользователей.

Мы поместим все наши пользовательские модели, маршруты конечных точек и функции контроллера в папку /api/user. Создайте следующие 4 файла в папке наших пользователей как таковые.

index.js — экспорт всех остальных файлов в папке в приложение.
user.controller.js — функции, которые запрашивают MongoDB.
>user.model.js — определение схемы MongoDB для пользователя.
user.routes.js — экспресс-маршруты, специфичные для этой модели пользователя.

Пользовательская модель

Прежде чем продолжить, вы должны прочитать библиотеку мангуста, в частности, как создать Модель. В этой части руководства мы создадим модель пользователя для коллекции пользователей в нашей базе данных. Модель User будет определять, какие поля мы будем сохранять для каждого пользователя. Ниже приведены столбцы, которые мы хотели бы сохранить для пользователя.

Имя — имя пользователя.
Электронная почта — адрес электронной почты, используемый для входа в систему.
Пароль — пароль пользователя ( мы хотим это как-то зашифровать)
Роль — Роль пользователя в приложении (гость, пользователь, админ)
Поставщик — Где зарегистрирован пользователь, локальный используется по умолчанию.
Соль —хэш, с помощью которого был зашифрован пароль.

Теперь, когда у нас есть определение модели. Поскольку мы назвали модель «Пользователь», mongoose теперь должен искать коллекцию users в нашей БД. Но мы можем просто указать имя коллекции, на которую мы ссылаемся, в качестве третьего параметра для mongoose.model();.

Пользовательский контроллер

Пришло время сохранить и извлечь данные из коллекции. В этом случае мы будем ссылаться на пользовательскую модель, которую мы создали на предыдущем шаге, чтобы вызывать функции, привязанные к этой модели определением схемы Mongoose. Вы можете найти полный список функций модели Mongoose здесь.

Мы будем генерировать 3 основные функции контроллера. Мы хотим иметь возможность получить список всех пользователей в коллекции пользователей, получить одного пользователя по электронной почте и сохранить нового пользователя. Скопируйте и вставьте приведенный ниже код в свой user.controller.js.

Любые новые функции, которые вы создаете, обязательно экспортируйте в конец файла user.controller.js. Просто добавьте их между скобками в экспорте модуля.

Потрясающий! Теперь мы можем находить, сохранять и перечислять пользователей из нашей коллекции пользователей. Но как Express узнает, когда вызывать эти функции? Здесь в игру вступает Express Endpoint (маршрут).

Пользовательские маршруты

Когда мы обращаемся к внешнему веб-сайту, мы в настоящее время обращаемся к нему через http://localhost:3000/. Сейчас мы хотим сделать так, чтобы любую новую конечную точку API, которую мы создаем, мы могли запрашивать через базовый URL-адрес http://localhost:3000/api/. Что касается маршрутов пользователей, мы хотим обрабатывать их под базовым URL-адресом http://localhost:3000/api/users/. Вот общее представление о маршрутах, которые мы надеемся зарегистрировать.

Откройте файл user.routes.js и вставьте приведенный ниже код. Вы заметите, что мы не регистрируем эти маршруты здесь с базовым URL-адресом /api/users, потому что мы назначим его в нашем файле routes.js. Только в целях организации.

До сих пор мы создали нашу модель пользователя, пользовательский контроллер и маршруты конечных точек пользователя. Нам все еще нужно экспортировать его в наш route.js, и наш файл index.js в папке пользователей справится с этим. Откройте файл index.js в папке /api/users, вставьте следующее и сохраните.

module.exports = require(./user.routes);

Нам не нужно экспортировать контроллер или Модель, так как маршруты включают в себя контроллер, а контроллер включает в себя Модель.

Зарегистрируйте новую конечную точку

В первой части этой серии мы создали файл routes.js в папке нашего сервера. Этот файл был создан для консолидации всех маршрутов и внедрения их в экспресс. Итак, теперь, когда мы создали пользовательские маршруты, мы можем зарегистрировать их и назначить им базовый URL-адрес. Добавьте следующее в файл routes.js, где указаны комментарии в файле.

app.use('/api/users', require('./api/users'));

Итак, давайте покроем этот новый маршрут. В route.js у нас есть функция с именем route(), в которую мы передаем параметр app и root. Параметр app содержит ссылку на экспресс-приложение. Итак, мы назначаем новый маршрут, вызывая app.use(). Теперь метод app.use() принимает два параметра. Первым из них является базовый URL-адрес пути, который вы назначаете этому маршруту, в этом случае мы хотим, чтобы все вызовы конечной точки пользователя были установлены на '/api/users.' Второй параметр, который мы импортируем конечные точки в нашей папке /api/users, поэтому нам требуется ('./api/users').

Тестирование конечной точки

Теперь есть разные способы проверить конечную точку. Вы можете протестировать его в браузере. Попробуйте запросить функцию listAllUsers конечной точки пользователей, набрав http://localhost:3000/api/users в браузере. Убедитесь, что вы запустили node app.js в терминале, чтобы запустить сервер узла.

Вы должны получить что-то вроде этого:

[] означает, что он пуст. Это потому, что в коллекции нет пользователей. Давайте откроем PostMan и попробуем создать пользователя. В почтальоне создайте новый POST-запрос к конечной точке http://localhost:3000/api/users и заполните тело запроса как объект json.

Мы получаем ответ с информацией о пользователе из функции Create в контроллере. Но есть очень большая проблема. Пароль не зашифрован. Это большая проблема по соображениям безопасности.

Есть два способа исправить это: мы можем либо хешировать это в функции создания, либо мы можем создать то, что называется крюком Mongoose, который появляется до или после определенной операции. Pre Hook используется перед выполнением определенной функции схемы.

Я думаю, что использование Schema Hooks намного чище, поэтому мы пойдем по этому пути. Сначала нам нужна библиотека для шифрования пароля. Установите следующую библиотеку:

Использование НПМ:

npm install --save-dev crypto

Использование пряжи:

yarn add --dev crypto

Теперь добавьте следующий импорт вверху файла users.model.js:

const crypto = require('crypto');

Эта библиотека поможет нам зашифровать пароль с помощью сгенерированной соли. Таким образом, мы сохраняем не фактический пароль пользователя, а хэш пароля, который мы можем позже расшифровать с помощью соли, чтобы обеспечить аутентификацию.

Добавьте следующий код после определения модели в файл users.model.js:

В файле у нас есть 1 хук и 2 метода схемы. Хук вызывается прямо перед выполнением метода save() для пользовательской схемы. Во время этого вызова хук вызывает две дополнительные функции, помогающие зашифровать пароль.

makeSalt() — генерирует случайный хеш с учетом размера в байтах или размера по умолчанию.

encryptPassword() — использует сгенерированный хэш для шифрования пароля.

Обе эти функции возвращают свои значения обратно в исходное место вызова, которым является функция create() в файле users.controller.js. Они возвращают и хэш, и зашифрованный пароль. Как только это будет сделано, пользователь будет сохранен с зашифрованным паролем и его хешем. Теперь, если мы сохраним все и перезапустим внутренний сервер, мы можем попытаться создать пользователя.

Теперь вы сможете опубликовать пользователя, получив документ пользователя с зашифрованным паролем и солью, которая использовалась для его шифрования. Это все еще не защищено, поскольку мы не должны видеть такого рода информацию. Что мы можем сделать, так это ограничить то, что мы можем просматривать, просто возвращая определенные поля пользователю.

Откройте файл user.controller.js и отредактируйте функцию создания:

Мы хотим вернуть только поля, которые мы можем использовать для отображения в приложении, но не какие-либо конфиденциальные. В этом случае мы возвращаем закодированный объект JSON с именем пользователя, идентификатором пользователя и ролью пользователя.

Связывание Frontend и Backend вместе с часами

Мы хотели бы иметь возможность запускать и отслеживать изменения во внешнем и внутреннем интерфейсе. Если есть изменения, мы хотим, чтобы проект автоматически перезапускался и перестраивался. Это легко сделать с помощью файла package.json.

В нашем файле package.json у нас есть раздел scripts, который содержит набор команд сценария, которые можно запустить. Здесь AngularCLI перечисляет команды ng build и ng serve. Мы можем связать команды с этими уже существующими и использовать флаг «наблюдать», чтобы отслеживать изменения и создавать, когда они есть.

Измените скрипт «build» с «ng build» на:

"build" : "ng build --watch & nodemon app.js --watch dist --watch server

Это заставит Angular CLI создать интерфейс в папке «dist». Затем Nodemon начинает отслеживать любые изменения в папках app.js, dist и server.

Настройка аутентификации пользователя во внешнем интерфейсе

В следующей части мы рассмотрим настройку простой формы входа, настройку службы аутентификации и защиту некоторых маршрутов.