如何跨多个模块访问节点acl?

How to access node acl across multiple modules?

我在理解如何将 Node ACL 与 mongoose 模块一起使用时遇到一些问题。只要所有内容都在一个文件中,我就可以得到它 运行。但是,如果我想将路由分解成单独的文件,如何访问其他模块中的 acl 实例?

我可以让 acl 使用以下代码正常工作。它初始化,在数据库中创建集合,并为用户添加权限。

// App.js
const mongoose = require('mongoose');
const node_acl = require('acl');
const User = require('./models/User');

mongoose.connect(/* connection string */);

acl = new node_acl(new node_acl.mongodbBackend(mongoose.connection.db, '_acl'));
acl.allow([
  {
    roles: ['guest'],
    allows: [{ resources: 'login', permissions: 'get' }],
  },
  {
    roles: ['admin'],
    allows: [{ resources: '/users', permissions: '*' }]
  }
]);

var user = User.findOne({username: 'coffee'}, (err, user) => {
  console.error(user.id);
  acl.addUserRoles(user.id, 'admin');
});

我想不通的是如何正确访问另一个模块中的 acl 实例。

// routes/foo.js
const acl = require('acl');
const router = require('express').Router();

// initialize acl ?

router.route('/', acl.middleware(/* rules */), (req, res) => {
  // route logic
});

module.exports = router;

此代码产生以下错误:TypeError: acl.middleware is not a function

是否需要在每个路由模块中使用数据库连接创建一个新的 acl 实例?如果是这样,再次从 Mongoose 获得连接的最佳方法是什么?如果没有,或者有没有办法将它传递给每条路线?

谢谢!

您可以通过请求变量共享对象:

app.js:

acl = new node_acl( new node_acl.mongodbBackend(mongoose.connection.db, '_acl'));
// add this before routers:
app.use( function( req, res, next) {
  req.acl = acl;
  next();
}); 

routes/foo.js:

router.route('/', (req, res) => {
  console.log(req.acl);
  // route logic
});  

我建议创建一个帮助程序模块,用于初始化 acl。然后,您可以在任何其他可能需要它的模块中使用它,例如您的路线。

正如 IOInterrupt 建议的那样,您应该创建一个辅助模块,下面是我如何让它工作的:

security.js

'use strict';

var node_acl = require('acl'),
    log = require('../log')(module),
    redis = require('../db/redis'),
    acl;

var redisBackend = new node_acl.redisBackend(redis, 'acl');
acl = new node_acl(redisBackend, log);
set_roles();

function set_roles () {

    acl.allow([{
        roles: 'admin',
        allows: [{
                resources: '/api/conf',
                permissions: '*'
            }
        ]
    }, {
        roles: 'user',
        allows: [{
            resources: 'photos',
            permissions: ['view', 'edit', 'delete']
        }]
    }, {
        roles: 'guest',
        allows: []
    }]);

    acl.addUserRoles('5863effc17a181523b12d48e', 'admin').then(function (res){
        console.log('Added myself ' + res);
    }).catch(function (err){
        console.log('Didnt worked m8' + err);
    });

}

module.exports = acl;

我第一次在 app.js

上调用它

app.js

// .. a bunch of other stuff 
var app = express();

require('./config/express')(app);
require('./config/routes')(app, jwtauth.jwtCheck);
require('./config/security'); // just like this

connect().on('error', console.log)
         .on('disconnected', connect)
         .once('open', function (){
            log.info('Connected to DB!!!');
         });
// .. a bunch of other stuff 

然后在我的路由文件中 conf.js 像这样:

conf.js

    log = require(libs + 'log')(module),
    acl = require('../config/security'),
    isauth = require(libs + 'auth/isAuthorized'),
    redis = require('../db/redis');

//               This is where the magic ensues
router.get('/', acl.middleware(2,isauth.validateToken,'view'), function (req, res) {
    Conf.findById(req.query.id).then(function (conf) {
        return res.json(conf);
    }).catch(function (err) {

不用担心在每次导入时调用 mongo 连接,因为在这里你将使用 require('../config/security') 所以他们都会得到相同的对象,因为导出是在您第一次在 app.js 调用它时缓存的。我的意思是,这将 不会 每次都创建一个 mongodb 连接。

您可以使用 app.locals 在应用程序中存储全局对象。,

在你的 app.js:

app.locals.acl = acl;

然后在任何请求中,您可以通过 req.app.locals.acl:

取回它
route.get('/some-resource', function (req, res, next) {

    let acl = req.app.locals.acl
    ...
}

https://expressjs.com/en/api.html#app.locals

结帐 app.locals 文档