1.0.1 • Published 8 years ago

koa-predicate-factory v1.0.1

Weekly downloads
1
License
MIT
Repository
github
Last release
8 years ago

koa-predicate-factory (WIP)

Why?

Checking authorization to resources in web-apps usually gets messy. Your beautiful succint RESTful API ends up looking like it went through deep spaghettization once you're done applying all the auth logic.

Usually, something like:

function *postArticle() {
    try {
      let res = yield Article.create(this.params);
      this.body = {success: true}
    } catch(err) {
      this.status = 400;
      this.body = {err: err}
    }
}
app.use(router.post('/article', createArticle);

Turns into:

function *postArticle() {
    let permissions = this.req.user && this.req.user.permissions ? this.req.user.permissions : null;
    if ( permissions && permissions.indexOf('create-article') > -1) {
        try {
          let res = yield Article.create(this.params);
          this.body = {success: true}
        } catch(err) {
          this.status = 400;
          this.body = {err: err}
        }    
    } else {
        this.status = 403;
        this.body = {err: 'Unauthorized'};
    }
}
app.use(router.post('/article', createArticle));

What's worse is that you end up redoing this permission checking mess over and over again with small changes. Great place to use the factory pattern. Wouldn't it be nicer to:

function *postArticle() {
    // .. code ..
}
app.use(router.post('/article', canCreateArticle(postArticle)));

Getting Started

Install:

npm install koa-predicate-factory

Create a predicate:

// predicates.js
'use strict';
const predicateFactory = require('koa-predicate-factory');

function hasValidApiKey() {
    // check something and return a boolean
    return this.request.headers['x-api-key'] == '21GL4hVbxDQz'
}

module.exports = {
    hasValidApiKey: predicateFactory(hasValidApiKey, 403, 'Not authorized');
}

Use it:

// index.js
'use strict';

const koa = require('koa')
  , router = require('koa-router')()
  , predicates = require('./predicates')
  ;

var app = koa();

app.use(router.routes())
   .use(router.allowedMethods())
   ;

router.get('/resource', predicates.hasValidApiKey(getResource));

function *getResource() {
    this.body = 'Hello, world!';
}

app.listen(8000);

API

predicateFactory(compareFn, errorCode, errorMessage)

Parameters

  • compareFn - a function that return true if the request should be processed
  • errorCode - an HTTP code to return if the check fails, i.e 403, 401, etc
  • errorMessage - if the check fails, this error message will be returned to the user like {"message": "<errorMessage>"}

Returns: function

predicateFactory returns a function which you can use to wrap your controller methods to decorate them with the permissions checking functionality.

Example

let isLoggedIn = predicateFactory(function() { /* ... */}, 401, 'Must be logged in');
app.use(isLoggedIn(controllers.home))