Не удалось добавить роли для пользователя с помощью метеор, используя пакет "ролей"
Я пытаюсь использовать пакет 'role', доступный в Atmosphere, но я не могу заставить его работать с Accounts.onCreateUser(), я могу привести пример в github. Когда я регистрирую пользователя, я хочу добавить к ним роль, когда я проверяю, назначена ли роль, она не подбирает его.
Здесь мой код
/server/users.js
Accounts.onCreateUser(function(options, user){
var role = ['admin'];
Roles.addUsersToRoles(user, role);
return user;
});
/client/page.js
Template.hello.events({
'click input': function () {
var loggedInUser = Meteor.user();
if (Roles.userIsInRole(loggedInUser, ['admin'])) {
console.log("Hi Admin!");
}else{
console.log("Please Log In");
}
}
});
Ответы
Ответ 1
Если вы посмотрите на код, используемый в пакете Roles
, вы увидите, что они используют ваш переданный в user/userId для выполнения запроса в пользовательской коллекции (здесь, начиная с строки ~ 623):
try {
if (Meteor.isClient) {
// On client, iterate over each user to fulfill Meteor's
// 'one update per ID' policy
_.each(users, function (user) {
Meteor.users.update({_id: user}, update)
})
} else {
// On the server we can use MongoDB $in operator for
// better performance
Meteor.users.update(
{_id: {$in: users}},
update,
{multi: true})
}
}
Так как onCreateUser
вызывается до того, как пользовательский объект вставлен в коллекцию (docs: возвращенный документ вставляется непосредственно в коллекцию Meteor.users), Roles
не может найти его при выполнении запроса.
Чтобы исправить это, вы должны подождать, пока пользователь не будет вставлен в коллекцию. Если вы посмотрите на пакет Roles
, все его примеры показывают это. Например here (второй пример, комментарии добавлены), а также многие другие:
// insert user and retrieve the id
id = Accounts.createUser({
email: user.email,
password: "apple1",
profile: { name: user.name }
});
// now we can verify that the user was inserted and add permissions
if (user.roles.length > 0) {
Roles.addUsersToRoles(id, user.roles);
}
Надеюсь, что светит свет на ваш вопрос. Таким образом, в основном просто вставьте пользователя, а затем добавьте разрешения после.
Ответ 2
Чтобы добавить вещи в пользовательский документ после того, как он был вставлен пакетом accounts
, попробуйте этот шаблон. Обратите внимание: вы должны meteor add random
генерировать userId
, что безопасно делать в этом контексте.
Accounts.onCreateUser(function (options, user) {
// Semantics for adding things to users after the user document has been inserted
var userId = user._id = Random.id();
var handle = Meteor.users.find({_id: userId}, {fields: {_id: 1}}).observe({
added: function () {
Roles.addUsersToRoles(userId, ['admin']);
handle.stop();
handle = null;
}
});
// In case the document is never inserted
Meteor.setTimeout(function() {
if (handle) {
handle.stop();
}
}, 30000);
return user;
});
Ответ 3
Я не понимаю, как интегрировать Roles.addUsersToRoles с функцией onCreateUser, вызванной при создании пользователя. Он не работает, когда вы вызываете его в OnCreateUser, как вы это делали, как вы уже нашли. Но пример случая вызова addUsersToRoles в цикле создания пользователя не представляется применимым к обычному случаю использования нового пользователя, создающего учетную запись.
Вместо этого я просто делаю:
Accounts.onCreateUser(function(options, user){
var role = ['admin'];
user.roles = role
return user;
});
Ответ 4
Принятый ответ заставляет вас написать шаблонный код для логина входа, заданный метеоритом через учетные записи - ui/password.
Другие ответы делают предположения о базовой реализации, а решение о тайм-ауте вводит условие гонки.
Почему бы не сделать это:
Accounts.onCreateUser(function(options, user) {
...
Meteor.setTimeout(function () {
Roles.addUsersToRoles(user._id, roles, group);
},0);
...
});
Ответ 5
Проблема здесь действительно сводится к поиску сообщения создать пользовательский крючок (который onCreateUser
нет).
Оказывается, такая вещь существует! Он назывался postSignUpHook
.
https://github.com/meteor-useraccounts/core/blob/master/Guide.md#options
Я нашел это из этого ответа SO:
fooobar.com/questions/208822/...
Это предпочтительный метод добавления ролей для пользователя, созданного с помощью шаблона UserAccounts (т.е. если вы не используете свой собственный Accounts.createUser
).
ОБНОВЛЕНИЕ
В конечном итоге я закончил использование matb33: collection-hooks в соответствии с этим комментарием:
https://github.com/alanning/meteor-roles/issues/35#issuecomment-198979601
Просто вставьте этот код в свой Meteor.startup, и все будет работать так, как ожидалось.
Ответ 6
Я не хотел переписывать логику, заданную пакетами счетов Meteor, самостоятельно устанавливать идентификатор или использовать setTimeout.
Вместо этого у меня есть код Tracker, наблюдающий за вызовом Meteor.user()
, который возвращает пользователя, если он зарегистрирован, и null, если нет.
Таким образом, эффективно, как только пользователь войдет в систему, этот код проверяет, назначена ли им роль, и если они не добавили их.
Мне пришлось использовать метод Meteor, потому что я не хочу, чтобы роли были запутаны на стороне клиента, но вы можете это изменить.
/* client */
Tracker.autorun(function () {
var user = Meteor.user();
if (user && !Roles.getRolesForUser(user).length) {
Meteor.call('addUserRole', user);
}
});
/* server */
Meteor.methods({
addUserRole: function (user) {
Roles.addUsersToRoles(user, user.profile.edmodo.type);
},
});
Ответ 7
Я так и сделал, и это довольно просто.
Я передаю роль как массив, поэтому я использовал [role]
На стороне клиента, когда пользователь подписывается:
var role = $(event.target).find('#role').val();
/*
* Add account - Client-Side
*/
Accounts.createUser(account, (error) => {
if (error) {
console.log(error);
} else {
// server-side call to add the user to the role
// notice Meteor.userId() and [role]
Meteor.call('assignUserToRole', Meteor.userId(), [role]);
// everything went well, redirect to home
FlowRouter.go('home');
}
});
В наших методах метеор (я использую метод lodash intersect для проверки роли, которую я хочу, чтобы пользователь выбирал)
Meteor.methods({
// when a account is created make sure we limit the roles
assignUserToRole: (userId, roles) => {
check(userId, String);
check(roles, Array);
var allowedRoles = ['student', 'parent', 'teacher'];
if (_.intersection(allowedRoles, roles).length > 0) {
Roles.addUsersToRoles(userId, roles, 'user');
} else {
Roles.addUsersToRoles(userId, ['student'], 'user');
}
}
});