2016-02-11 29 views
1

我在理解如何使用貓鼬模塊使用Node ACL時遇到了一些麻煩。只要一切都在一個文件中,我就可以很好地運行。但是,如果我想將路由分解成單獨的文件,如何訪問其他模塊中的acl實例?如何跨多個模塊訪問節點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(); 
}); 

路線/ foo.js:

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

回答

2

由於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) { 

不要擔心調用蒙戈連接被稱爲在每個進口,因爲在這裏你」將使用require('../config/security'),因此它們將獲得相同的對象,因爲在您第一次調用它時,導出緩存在app.js。我的意思是,這將而不是每次創建一個mongodb連接。

+1

謝謝!這樣做更有意義。 – JeremyC

3

您可以通過請求變量共享對象模塊,它初始化acl。然後,您可以在任何其他可能需要的模塊中要求它,例如您的路線。

+0

在那個例子中'ACL app.locals文件。中間件()'仍然是未定義的,直到你在處理程序中獲得請求對象,所以中間件仍然無法正常工作,對吧? – JeremyC

+0

@JeremyC只需刪除它,更新示例。 –

0

我建議建立一個輔助

+0

如果我編寫一個可以初始化acl的幫助程序模塊,是否不會創建數十個到數據庫的連接?或者它只是連接一次? – JeremyC

0

您可以使用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