2016-02-11 3 views
1

У меня возникли проблемы с пониманием того, как использовать Node ACL с модулем mongoose. Я могу заставить его работать нормально, пока все в одном файле. Однако как мне получить доступ к экземпляру 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; 

0 0 Код ошибки: TypeError: acl.middleware is not a function.

Нужно ли создать новый экземпляр acl, используя соединение с базой данных в каждом модуле маршрута? Если да, то какой лучший способ снова получить соединение с Mongoose? Если нет, или есть способ передать его каждому маршруту?

Спасибо!

ответ

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

Вы можете поделиться объект по запросу переменной:

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 
}); 
+0

В этом примере 'ACL. middleware() 'все еще не определено до тех пор, пока вы не получите объект запроса в обработчике, поэтому промежуточное ПО все еще не будет работать правильно, не так ли? – JeremyC

+0

@JeremyC Просто удалите его, обновите пример. –

0

Я бы предложил создать помощника модуль, который инициализирует acl. Затем вы можете потребовать его в любых других модулях, которые могут потребоваться, например, в ваших маршрутах.

+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 
    ... 
} 

заказ app.locals документ на https://expressjs.com/en/api.html#app.locals

Смежные вопросы