Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Rapid API Development with SailsJS

Rapid API Development with SailsJS

Creating a RESTful API should be the easiest part of your development. You should not have to be a rocket scientist to successfully create a RESTful API. With Sails, you can create a full featured RESTful API in just a few minutes without writing any code. You get create, destroy, update, find, paginate, sort, and filtering out of the box. If you need to add your business logic to any of the methods or create your own methods, you can do that by writing simple JavaScript functions. Once you are ready to implement security, Sails provides policies that can be applied to any REST action to implement email/password, social login or Windows authentication. For data storage, Sails bundles the power ORM, Waterline, which provides a simple data access layer that just works, no matter which one of the more than 30 data storage providers you are using.

This talk will be code heavy as we walk through getting started with Sails and demonstrate how to implement the features of Sails through the creation of an API. As well, I will share the tips and tricks that I have learned using Sails at a Fortune 100 company. You will walk away understanding how and why you should use Sails on your next project. All code covered in the talk with be immediately available for download.

Avatar for Justin James

Justin James

May 02, 2018

Other Decks in Programming

Transcript

  1. https://digitaldrummerj.me @digitaldrummerj represents a record usually maps to db table

    attributes map to columns Models 22 sails generate model
  2. https://digitaldrummerj.me @digitaldrummerj Responds to requests Bound to routes Structured way

    to create an action 1 file per action Self-documenting and validating Action sails generate action [ctrl/name] 26
  3. https://digitaldrummerj.me @digitaldrummerj 200 – ok, send 500 - serverError 404

    - notFound 403 - forbidden 400 – badRequest [Code] – json, send Standard Responses 28
  4. https://digitaldrummerj.me @digitaldrummerj Exposes a set of commonly-used functions as Sails

    helpers Examples: password: hash and check gravatar: get avatar url stripe: bill info and charging Optional Helpers npm i sails-hook-organics --save 30
  5. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 33
  6. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 34
  7. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 35
  8. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 36
  9. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 37
  10. https://digitaldrummerj.me @digitaldrummerj Override Controller Example module.exports = { find: function

    findFn(req, res) {}, // GET findOne: function findOneFn(req, res) {}, // GET/id create: function createFn(req, res) {}, // POST update: function updateFn(req, res) {}, // PUT destroy: function deleteFn(req, res) {}, // DELETE } 38
  11. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 39
  12. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 40
  13. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 41
  14. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 42
  15. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 43
  16. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE 44
  17. https://digitaldrummerj.me @digitaldrummerj Override Action Example api\controllers\[controller]\find.js // GET api\controllers\[controller]\find-one.js //

    GET/id api\controllers\[controller]\create.js // POST api\controllers\[controller]\update.js // PUT api\controllers\[controller]\destroy // DELETE sails generate action [controller]/[action] 45
  18. https://digitaldrummerj.me @digitaldrummerj Execute some logic before an action to determine

    if request is processed Stored in api\policies folder Configured in api\config\policies.js Route Security 46
  19. https://digitaldrummerj.me @digitaldrummerj Security – api\policies\isLoggedIn.js module.exports = function(req, res, proceed)

    { if (req.session.user) return proceed(); return res.forbidden('Please Login First.'); }; 47
  20. https://digitaldrummerj.me @digitaldrummerj Security – api\policies\isLoggedIn.js module.exports = function(req, res, proceed)

    { if (req.session.user) return proceed(); return res.forbidden('Please Login First.'); }; 48
  21. https://digitaldrummerj.me @digitaldrummerj Security – api\policies\isLoggedIn.js module.exports = function(req, res, proceed)

    { if (req.session.user) return proceed(); return res.forbidden('Please Login First.'); }; 49
  22. https://digitaldrummerj.me @digitaldrummerj Security – api\policies\isLoggedIn.js module.exports = function(req, res, proceed)

    { if (req.session.user) return proceed(); return res.forbidden('Please Login First.'); }; 50
  23. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 51
  24. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 52
  25. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 53
  26. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 54
  27. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 55
  28. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Controller – config\policies.js module.exports.policies =

    { UserController: { create: ['isLoggedOut'], login: true, '*': ['isLoggedIn'], }, TodoController: { '*': ['isLoggedIn'] } } 56
  29. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Action – config\policies.js module.exports.policies =

    { 'user/*': ['is-logged-in'], 'user/create': ['is-logged-out'], 'user/login': true, 'todo/*': ['is-logged-in'], } 57
  30. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Action – config\policies.js module.exports.policies =

    { 'user/*': ['is-logged-in'], 'user/create': ['is-logged-out'], 'user/login': true, 'todo/*': ['is-logged-in'], } 58
  31. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Action – config\policies.js module.exports.policies =

    { 'user/*': ['is-logged-in'], 'user/create': ['is-logged-out'], 'user/login': true, 'todo/*': ['is-logged-in'], } 59
  32. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Action – config\policies.js module.exports.policies =

    { 'user/*': ['is-logged-in'], 'user/create': ['is-logged-out'], 'user/login': true, 'todo/*': ['is-logged-in'], } 60
  33. https://digitaldrummerj.me @digitaldrummerj Implement Policy – Action – config\policies.js module.exports.policies =

    { 'user/*': ['is-logged-in'], 'user/create': ['is-logged-out'], 'user/login': true, 'todo/*': ['is-logged-in'], } 61
  34. https://digitaldrummerj.me @digitaldrummerj Allows scripts served from other domains Disabled By

    Default Origin can be array of urls App wide or individual routes CORS 62 config/security.js
  35. https://digitaldrummerj.me @digitaldrummerj Attack that forces user to execute unwanted actions

    on an API they are authenticated with CSRF Tokens tells server they "were where they say they were" Used on all Non-Get request Cross-site request forgery (CSRF) 63 config/security.js
  36. https://digitaldrummerj.me @digitaldrummerj Routes – config/routes.js – Controller Functions // Controller

    functions module.exports.routes = { 'GET /todo/:id': TodoController.findOne', }; 65
  37. https://digitaldrummerj.me @digitaldrummerj CODING TIME Todo API - users have to

    login to see data - users can only see their data - users can only register once - passwords must be hashed - todo items associated to users 67