Reputation: 33
I am fairly new to Meteor and have been having real trouble with this issue.
I would like to have a select element which updates the users role (once logged in) depending on the option selected. I'm storing the value of the option as a variable when the select is changed and trying to take this value as the name of the role to add to the user.
When I run my app and change the select, the role seems to pop up for a second (viewed in Mongol) before disappearing again. I created a small test to display an alert of the role for the user, which shows up containing the name of the role but once you OK it, the role has disappeared. Am I missing something here?
Here is my template containing the select element...
<template name="select">
<select id="select">
<option value="working">Looking for work</option>
<option value="hiring">Hiring</option>
</select>
</template>
And here is the client side code for the change event
Template.select.events({
'change #select': function (event) {
//remove any current roles added to the user as it will be either
//one or the other
Roles.removeUsersFromRoles( Meteor.userId(), 'working', 'hiring' );
//add a role to the current user with the value from select box
var value = $(event.target).val();
Roles.addUsersToRoles( Meteor.user(), value );
//each of these alerts displays correctly depending on the select
//value
var test = Roles.userIsInRole( Meteor.user(), 'hiring' ); // true
if (test===true){
alert('in hiring role');
}
var test2 = Roles.userIsInRole( Meteor.user(), 'working' ); // true
if (test2===true){
alert('in working role');
}
// either working or hiring
alert(Roles.getRolesForUser(Meteor.userId()));
// alert displays count of 1 when you select 'hiring'
alert(Roles.getUsersInRole('hiring').count());
}
});
Any help would be much appreciated, have been searching through the documentation and online for several days to no avail. Many thanks :)
Upvotes: 0
Views: 166
Reputation: 8413
You try to add roles in your client. However, the client reflects only the data from the server's Roles
collection.
You need therefore to change your code to a server side method, that
a) checks wether the current user is permitted to change roles (warning here, potential security threats when not checking permissions)
b) checks, wether the targeted user exists
c) sets the roles for the given userId
There is a good example in the documentation on how to do that. This is a slightly modified version of it:
Meteor.methods({
'updateRoles'({userId, roles, group}) {
check(userId, String);
check(roles, [String]);
check(group, String);
// a) check permission
if (!this.userId || !Meteor.users.findOne(this.userId) || !Roles.userIsInRole(this.userId, 'update-roles', 'lifted-users'))
throw new Meteor.Error('403', 'forbidden', 'you have no permission to change roles');
// b) check target user
if (!Meteor.users.findOne(userId))
throw new Meteor.Error('404', 'user not found');
// c) update user's roles
Roles.setUserRoles(userId, roles, group);
return true;
}
});
This method assumes, that there is a special role/group combination for users, that are allowed to change roles. This should be only a very few people, like admins.
Also note, that this method sets the user roles by using Roles.setUserRoles
. If you want to extend the roles you need to use Roles.addUserToRoles
.
You can then call this method from your client like every Meteor method:
Template.select.events({
'change #select': function (event) {
// get value from select box
var roles = [$(event.target).val()];
// TODO create a second select for the group
var group = 'defaultUsers'
var userId = Meteor.userId();
Meteor.call('updateRoles', { userId, roles, group }, (err, res) => {
// handle err / res
console.log(Roles.userIsInRole(userId, roles, group)); // should return true
});
}
});
Note, that Roles
on the client is a collection which is immediately subscribed to. Changes are reflected reactively. If you do not see the changes immediately
Upvotes: 0