Get sails request target from policy scope

2019-03-31 00:30发布

问题:

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

回答1:

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];
    }
  }
};