railroad
v0.3.2
Published
Build Node REST API's with the annoying stuff already done for you.
Downloads
14
Readme
Railroad
Basic framework for rest api's based on koa and uses Waterline models.
Features:
- Automatic REST controllers with support for authentication and authorization.
- Authentication middleware (Json Web Tokens or custom implementation).
- Configure ACL for controllers and actions.
- ACL based on the current user (e.g. a user can only edit itself).
- Pagination
- Etag and Conditional GET
Usage
let koa = require('koa');
let Railroad = require('railroad');
let config = require('./config');
let app = koa();
Railroad(app, config, {
acl: require('./acl'),
auth: require('./auth')
}).then(() => {
app.listen(3000);
}).catch((err) => {
console.log(err.stack);
});
Configuration
// config.js
let path = require('path');
let connections = require('./connections');
let routes = require('./routes');
module.exports = {
// Path to the controllers directory
controllers: path.join(__dirname, 'controllers'),
// Path to the models directory
models: path.join(__dirname, 'models'),
connections: connections,
routes: routes,
// Options for resource controllers/actions.
resource: {
pagination: true, // turn on pagination
pageLimit: 50 // If pagination is turned on, set the limit per page
}
// Options for Json Web Tokens (if you want to use it)
jwt: {
expiresIn: 180 * 60,
secret: 'secret'
}
};
Database connections
The database connection configuration is a configuration object for the Waterline ORM.
// connections.js
let diskAdapter = require('sails-disk');
/**
* Waterline ORM config.
*/
module.exports = {
adapters: {
default: diskAdapter,
disk: diskAdapter
},
connections: {
myLocalDisk: {
adapter: 'disk'
}
},
defaults: {
connection: 'myLocalDisk',
migrate: 'safe'
}
};
Resource Controllers
A resource controller will provide all the CRUD operations for a model. It taps into the
authentication and authorization functionality. It will use the global pagination configuration, or you can
pass an optional options object. A Resource
will return an object. Example:
let Resource = require('railroad/lib/utils/Resource');
// model name and optional "resource" options
module.exports = Resource('User', { pagination: false });
A resource has the following methods:
- find: GET method, returns an array with resources.
- findOne: GET method, returns a single resource
- create: POST method, create a resource and return it.
- update: PATCH method, update a resource and return it.
- destroy: DELETE method, delete a resource.
If you do not need all methods, you could make your own controller and use the action
helpers individually (located in railroad/lib/utils/ResourceAction
).
Pagination
By default a Resource
has pagination on the find
method. Query parameters page
and limit
are used to control the pagination.
A response will include Link Headers for navigation to other pages.
To turn off pagination pass the following option into the resource function:
Resource('User', { pagination: false });
Routes
The routes configuration maps paths to controllers or actions. For a resource controller, just use the path. For a custom controller action, add the method as a prefix. Example route configuration:
// routes.js
module.exports = {
'/product': 'ProductController', // Resource route
'get /product/custom': 'ProductController.custom', // Custom route
'get /product/custom/:title': { // Custom route alternate syntax
controller: 'ProductController',
action: 'customOne'
},
'/pet': 'animals/PetController' // Nested file
};
Authentication
A middleware is used to authenticate a user. An example:
// auth.js
module.exports = function* (next) {
if (!this.state.route.requiresAuth) {
return yield next;
}
this.state.user = {
id: 2,
name: 'Test User',
isAdmin: false
};
return yield next;
};
Railroad includes an auth middleware and controller that uses Json Web Tokens. See the example.
Authorization
The ACL file must export a function with the user as it's argument. An object explaining the rights of the user must be returned from this function.
Properties names of this object can be controller names, (action names nested within a controller)
or *
for defining the default ACL.
Values can be a boolean, function or an object.
- boolean: When set to
true
, authentication is required. - object: Authentication is required, but authorization depends on the accessed resourced. The object will describe criteria that applies to the Waterline model. It is basically a where clause.
- function: Authentication is required, but the outcome of the function will decide if a user has access. A function can either return a boolean or an object. Depennding on the type, one of the previous rules will apply.
module.exports = function (user) {
return {
'*': true, // All routes protected by default
'animals/PetController': false, // Allow PetController
ProductController: {
find: {
userId: user.id
},
custom: true, // Require auth
customOne: () => user.isAdmin, // Conditional Acl with a function
create: false,
findOne: {
userId: user.id // Conditions for the Waterline model
},
update: {
userId: user.id
},
destroy: {
userId: user.id
}
}
}
};
Context added by Railroad
- ctx.config: The railroad configuration object.
- ctx.state.route.controllerName: Name of the current controller.
- ctx.state.route.actionName: Name of the current action.
- ctx.state.route.path: Path as defined in the route configuration.
- ctx.state.route.method: Method of the current route.
- ctx.state.route.requiresAuth: Check if the current route requires authentication.
- ctx.state.user: The current user.
- ctx.state.route.acl.authenticated: If the current user is authenticated.
- ctx.state.route.acl.authorized: If the current user is authorized to access the current route.
- ctx.state.route.acl.criteria: Criteria for the current route as defined in the acl middleware.