Написание простого блога на SailsJS: наглядная практика для начинающих (Часть 2)

Синопсис Ранее мы изучили написание основы для нашего блога, при написании основы мы ознакомились с организацией статики, составлением модели и написанием кода контроллера. Узнали как можно работать с конфигурациями путей (routes.js), и как работать с представлениями в SailsJS. Во второй части о написании простого блога на SailsJS, мы рассмотрим следующие пункты: Пользователи: создание. Сессии: создание (вход), разрыв (выход). Написание Админ Панели, и работа с политикой и ограничениями доступа.

Пользователи Для создания нового комплекса API вводим уже знакомую нам команду в корне нашего проекта. sails generate api user В этот раз при организации кода нам понадобится шифровать пароль, для этого нам потребуется отличный модуль password-hash, который подойдет для этой задачи. Чтобы его установить — в корне нашего проекта введите следующую команду npm install password-hash --save Параметр --save указывает на то что мы сохраним значение модуль как зависимость в package.json.Так как в предыдущем посте я уже рассмотрел базовые навыки работы с моделями и контроллерами в SailsJS — где они находятся, и как их правильно составлять, я не буду обращать внимания на уже очевидные вещи.

Модель Для нашего пользователя будет несколько атрибутов: Имя пользователя Пароль Админ — параметр доступа При составлении модели мы не должны забывать что мы хотим также сделать шифрование пароля на сервере, а также сделать несколько дополнительных вспомогательных функций основанные на работе с жизненными циклами моделей var passwordHash = require ('password-hash');

var User = {

attributes: {

username: {type: 'string', required: true, unique: true}, password: {type: 'string', required: true, minLength: 8},

admin: { type: 'boolean', defaultsTo: false }, toJSON: function () { var element = this.toObject (); delete element.password; return element; }

},

beforeCreate: function (values, next) { // Создаем зашифрованную запись пароля в БД var mainPass = passwordHash.generate (values.password); values.encryptPassword = mainPass; next (); }

};

module.exports = User;

До создания нового пользователя мы добавляем дополнительный атрибут — encryptedPassword, который представляет собой зашифрованную версию пароля.Контроллер В контроллере мы сделаем только возможность создавать пользователя, и индексную страницу. Как сделать обработчики обновления и удаления пользователя вы сможете сами по подобию того что мы сделали в контроллере постов. Вот код контроллера. module.exports = {

//@API — создание пользователя

/** * Создание нового пользователя, * в качестве параметров передаем * имя пользователя, пароль, и булевое * значение админ. После создания * пользователя он аутентифицируется * в сессии. После создания пользователя * администратора мы установим политику * admin (api/policies/admin.js) чтобы к * этой функции больше не могли обращаться * не привелегированные пользователи */ create: function (req, res) { var elem = { username: req.param ('username'), password: req.param ('password'), admin: req.param ('admin') };

User.create (elem).exec (function (err, user) { if (err) return res.send (500); req.session.auth = true; res.redirect ('/'); }); },

// @MAIN index: function (req, res) { res.view (); } };

В конфигурации путей (config/routes.js) добавим следующее. '/register' : 'UserController', В качестве простой защиты включим защиту CSRF в файле конфигурации (config/csrf.js) отредактируем строку следующим образом module.exports.csrf = true; Представление (views/user/index.ejs) А теперь составим представление, оно будет иметь простейшую структуру.



Или же вместо представления можно просто отключив csrf создать пользователя — например с помощью Postman. А потом заблокировать контроллер Пользователей.На этом завершим написание составляющих для создания пользователей. Теперь у нас есть модель, контроллер, путь страницы регистрации, и шаблон представления.

Сессии Для авторизации пользователей мы будем использовать встроенную в Sails систему сессий — это удобно и достаточно безопасно (если сравнивать с cookie) наш контроллер сессий сможет создавать сессии и уничтожать их. Создайте новый контроллер стандартным способом. Вот код нашего контроллера. var passwordHash = require ('password-hash');

module.exports = {

// @API основные функции сессии

create: function (req, res) { /** * Задаем переменные запрашиваемых * параметров, в нашем случае логин * и пароль */ var username = req.param ('username'), password = req.param ('password');

/** * Если нет логина или пароля в запросе * вывести ошибку, и перенаправить обратно * (прим. здесь лучше сделать подробную * обработку ошибок, например с flash) */

if (! username || ! password) { return res.redirect ('/session'); };

/** * Найти пользователя из запроса логина * (username — req.param ('username')) * когда пользователь найден производиться * сравнение зашифрованного пароля с паролем * который был отправлен запросом, если он * валиден, то создается внешний статус — * авторизован или нет, и дается доступ к * данным через внешний доступ сессии. Это * позволит нам в дальнейшем создать политику * для ограничивания доступа к определенным * разделам нашего блога (используя сессии) */ User.findOneByUsername (username).exec (function (err, user) { if (! user || err) return res.send (500); if (passwordHash.verify (password, user.encryptPassword)) { // Авторизовать пользователя в сессии // Дать доступ к данным авторизованного // пользователя из сессии req.session.auth = true; req.session.User = user; if (req.session.User.admin) { return res.redirect ('/admin'); }; }; }); }, /** * Создаем выход из сессии который * просматривает есть ли пользователь * в онлайне, и уничтожает сессию */ destroy: function (req, res) { User.findOne (req.session.User.id).exec (function (err, user) { if (user) { req.session.destroy (); res.redirect ('/'); } else { res.redirect ('/login'); }; }); },

// @MAIN

index: function (req, res) { res.view (); } }; Конфигурация путей '/login' : 'SessionController', '/logout' : { controller: 'session', action: 'destroy' }, Представление И представление страницы входа

Sign-in form




Теперь мы создали возможность регистрироваться и создавать сессии (входить с систему), теперь осталось сделать страницу админ панельки, и настроить политику разграничения доступа. И так завершающий этап.Админ Панель и Разграничение Прав У нас будет простейшая страница админки состоящая из списка постов, и формы добавления нового поста. А также страница для редактирования уже существующих постов. Теперь создайте новый контроллер admin. Вот код нашего контроллера.

module.exports = { index: function (req, res) { Post.find () .sort ('id DESC') .exec (function (err, posts) { if (err) return res.send (500); res.view ({ posts: posts }); }); },

edit: function (req, res) { var Id = req.param ('id');

Post.findOne (Id).exec (function (err, post) { if (! post) return res.send (404); if (err) return res.send (500); res.view ({ post: post }); }); } }; И 2 наших представления.views/admin/index.ejs

CREATE NEW




POST LIST

<% _.each(posts, function (post) { %>
ID TITLE
<%= post.id %> <%= post.title %> » class=«btn btn-danger»>Delete

Title

А теперь займемся созданием политики.

Политика Система разграничения прав доступа в Sails весьма удобна и проста в использовании, в нашем случае достаточно лишь сверить чтобы пользователь: Был Авторизован И являлся администратором Чтобы выразить это в коде создадим файл нашей политики — api/policies/admin.js. И вот код нашего разграничителя. module.exports = function (req, res, ok) { if (req.session.auth && req.session.User.admin) { return ok (); } else { return res.redirect ('/login'); }; } В данном случае коллбек возвращается для того чтобы пропустить дальнейшие действия. если результат противоположный — запретить и перенаправить на страницу входа. Для активации нашей политики на определенном контроллере — откройте файл config/policies.js и приведите его в следующий вид. module.exports.policies = {

// Default policy for all controllers and actions // (`true` allows public access) '*': true,

/** * Вставляем для нашего контроллера * Admin политику admin.js, которая * ограничивает доступ. */

AdminController: { '*': 'admin' },

UserController: { create: 'admin' },

PostController: { // То что могут видеть все index: true, page: true, watch: true,

// То что может только админ create: 'admin', update: 'admin', delete: 'admin', } }; На этом мы закончим написание простого блога на Sails, конечно в нем очень мало функционала и защиты — нет обработки ошибок (даже flash сообщений), нет полноценной мультипользовательской админки, но эта статья расcчитана как маленький вводный курс в этот фреймворк, дальше можете изучать его сами. В дальнейшем нарастить функционал вам не должно составить большого труда.

© Habrahabr.ru