Волокна Узла Беда с Метеором
Я пытаюсь написать простой бэкэнд аутентификации для Meteor, который аутентифицируется на сервере LDAP. Мне нужна функция, зарегистрированная в качестве обработчика входа (вход в Accounts.registerLoginHandler
) вернуть id
пользователя только что вошел в систему.
Проблема, я думаю, заключается в волокне, которое я создал, getUserId
и что он не возвращается id
как я этого хочу. Я знаю, что это должно быть в Волокне, иначе метеор рассердится и выдаст ошибки. Хотя журнал прямо перед yield
показывает мне id
не определено, getUserId.run()
всегда возвращает неопределенное.
Любая помощь будет принята с благодарностью, спасибо!
Accounts.registerLoginHandler(function(loginRequest) {
console.log("In login handler");
return auth.authenticate(loginRequest.username, loginRequest.password, function(err, ldap_user) {
if (err){
// ldap authentications was failed
console.log("Login failed");
return undefined;
}
else {
// authentication was successful
console.log("Login success");
// extracting team name from ldap record
var equals = ldap_user.memberOf.indexOf("=");
var comma = ldap_user.memberOf.indexOf(",");
var team_name = ldap_user.memberOf.slice(equals+1,comma);
// add user if they don't already exist
var getUserId = Fiber( function() { // Meteor code must be ran within a fiber
var id = null;
var user = Meteor.users.findOne({username: loginRequest.username});
if(!user) {
// insert user and kick back id
id = Meteor.users.insert({username: loginRequest.username,
profile : {team : team_name}
});
console.log('no user found, creating' + id);
} else {
id = user._id;
console.log('user found, returning id' + id);
}
console.log('id: '+id);
Fiber.yield(id); // return id
});
// send logged in users if by executing the fiber
return {id: getUserId.run()};
}
});
});
1 ответ
Я думаю, что проблема связана с необходимостью использования Meteor.bindEnvironment
контролировать область действия переменных (среды) и используемых волокон.
Хороший трехступенчатый учебник по этому вопросу находится здесь:
- https://www.eventedmind.com/feed/nodejs-introducing-fibers
- https://www.eventedmind.com/feed/meteor-dynamic-scoping-with-environment-variables
- https://www.eventedmind.com/feed/meteor-what-is-meteor-bindenvironment
Мой взгляд на ваш код будет выглядеть примерно так (что в аналогичной задаче сработало для меня):
Accounts.registerLoginHandler(function(loginRequest) {
console.log("In login handler");
var boundAuthenticateFunction = Meteor.bindEnvironment(function(err, ldap_user) {
if (err){
// ldap authentications was failed
console.log("Login failed");
return undefined;
}
else {
// authentication was successful
console.log("Login success");
// extracting team name from ldap record
var equals = ldap_user.memberOf.indexOf("=");
var comma = ldap_user.memberOf.indexOf(",");
var team_name = ldap_user.memberOf.slice(equals+1,comma);
// add user if they don't already exist
var id = null;
var user = Meteor.users.findOne({username: loginRequest.username});
if(!user) {
// insert user and kick back id
id = Meteor.users.insert({username: loginRequest.username,
profile : {team : team_name}
});
console.log('no user found, creating' + id);
} else {
id = user._id;
console.log('user found, returning id' + id);
}
console.log('id: '+id);
return {id: id};
}
}, function(e){throw e;});
return auth.authenticate(loginRequest.username, loginRequest.password, boundAuthenticateFunction);
});
Имейте в виду, пример кода выше не проверен...