I currently try to set up a simple authorization system (authentication already in place) for a sails (v0.10) application based on the policy system sails provides. For this purpose I'd need to get the controller and action the current request targets from within my policy.
I'd do roughly do the following in the policy:
module.exports = function (req, res, next) {
// Get target controller and action
var target = req.target; // How to do this?
var action = req.action; // and this?
// Lookup in database, let through if matches or render error
User.findOne...
};
I recall the target information was embedded in the request object at some point but isn't found there now (commit 5d98ec8).
I am aware of the possibility to parse req.route and get the needed information by mimicking the sails router, but I'd rather avoid duplicating the routing logic for the sole purpose of a policy.
Edit:
The controller identity can be retrieved from the request object like this:
var controller = req.options.controller || req.options.model;
Example req.options:
{ detectedVerb: { verb: '', original: '/user/:id?', path: '/user/:id?' },
associations:
[ { alias: 'auth', type: 'model', model: 'key' },
{ alias: 'group', type: 'model', model: 'group' },
{ alias: 'role', type: 'model', model: 'role' } ],
actions: true,
rest: true,
shortcuts: true,
prefix: '',
pluralize: false,
index: true,
model: 'user' }
Still hunting for a sane way to get the target controller action.
- Related Issue: https://github.com/balderdashy/sails/issues/1372
- Relate Google Group Posting: https://groups.google.com/forum/#!topic/sailsjs/faX54hqcNZE
Based on the feedback on the Github issue about this I decided to write up a target action/target blueprint lookup as custom service leaning on the route bindings found in sails.hooks.blueprints
.
Usage:
var action = Utility.getRequestAction(req);
The service definition:
/**
* api/services/Utitlity.js
*
* @module Service
* @name Utility
* @memberOf global
* @description Utilities for various common tiny tasks
* @docs http://sailsjs.org/#!documentation/services
* @api public
**/
/**
* Module dependencies
*/
var util = require('util'),
_ = require('lodash');
module.exports = {
getRequestAction: function (req) {
if (req.options.action) return req.options.action;
var controller = req.options.controller || req.options.model;
var baseRoute = sails.config.blueprints.prefix + controller;
var requestRoute = req.route.method + ' ' + req.route.path;
var Model = sails.models[controller];
if (req.options.shortcuts && Model) {
var shortcutRoutes = {
'/%s/find/:id?': 'find',
'/%s/create': 'create',
'/%s/update/:id?': 'update',
'/%s/destroy/:id?': 'destroy'
};
var shortcutAction = _.findWhere(shortcutRoutes, function(blueprint, pattern){
var shortcutRoute = util.format(pattern, baseRoute);
return req.route.path === shortcutRoute;
});
if (shortcutAction) return shortcutAction;
}
if (req.options.rest && Model) {
var restRoutes = {
'get /%s/:id?': 'find',
'post /%s': 'create',
'put /%s/:id?': 'update',
'delete /%s/:id?': 'destroy'
};
var restAction =_.findWhere(restRoutes, function(blueprint, pattern){
var restRoute = util.format(pattern, baseRoute);
return requestRoute === restRoute;
});
if (restAction) return restAction;
var associationActions = _.compact(_.map(req.options.associations, function(association){
var alias = association.alias;
var associationRoutes = {
'get /%s/:parentid/%s/:id?': 'populate',
'post /%s/:parentid/%s': 'add',
'delete /%s/:parentid/%s': 'remove'
};
return _.findWhere(associationRoutes, function(blueprint, pattern){
var associationRoute = util.format(pattern, baseRoute, alias);
return requestRoute === associationRoute;
});
}));
if (associationActions.length > 0) return associationActions[0];
}
}
};