Hi, Im new to Meteor. I have already followed some tutorials and books to learn the basics of Meteor. But is there a good tutorial on how to create an admin panel which is restricted to the normal users?
Thanks in advance
Hi, Im new to Meteor. I have already followed some tutorials and books to learn the basics of Meteor. But is there a good tutorial on how to create an admin panel which is restricted to the normal users?
Thanks in advance
Easier than youâd think
Start by using a library like alanning:roles
to put users in roles. Eg:
Meteor.startup(function () {
const admins = ['admin@admin.org', 'admin2@admin.org'].map(email => Accounts.findUserByEmail(email));
Roles.addUsersToRoles(admins, 'admin', Roles.GLOBAL_GROUP);
});
Hereâs a small catch: They can render the admin page, but since meteor is data driven, you just publish information to the admins. They may render the page, but they wonât have any information.
Meteor.publish('adminData', function () {
if (Roles.userIsInRole(this.userId, 'admin', Roles.GLOBAL_GROUP)) {
return SecretData.find();
} else {
this.error(new Meteor.Error(403, "Access Denied"));
}
});
Cool! Thatsâs great news. But according to what I understand, meteor loads all the files at first. But what if we want to stop loading the admin related js and html files from loading to normal users? Is it possible to do this?
Also is it possible to restrict a specific route and all itâs sub routes to normal users? Iâm planning to use the FlowRouter.
You canât, really, you just restrict the data that they receive and what they can do.
Sure, they can render the admin page, but you can just make it not show anything of value. Or even better, make an access denied
screen.
template(name="Admin")
if isInRole 'admin'
// your template data here
else
h1 Invalid Permissions.
I use the Roles package, and have added a few layers of security based around that.
Router-level: You canât restrict the route directly based around role, but if your using the useraccounts package, you can require the user be logged in, at which point you can THEN check their role. Example (using FlowRouter and Blaze):
FlowRouter.route(â/dashboard/â, {
triggersEnter: [AccountsTemplates.ensureSignedIn],
action: function() {
BlazeLayout.render(âlayoutâ, {main: âdashboardâ});
}
});
Template-level security: In my primary Layout template I have a block that builds upon the above route based security. It (again) checks for login, and then checks for role. If the user is of a desirable role, the layout will be rendered. If not, access denied. Example:
{{#if authLoggedIn}}
{{#if isInRole 'superadmin,admin,user'}}
{{>mainLayout}}
{{else}}
{{>accessDenied}}
{{/if}}
{{else}}
Publication-level: The above is all client based security. Of course, some malicious users may be able to find a way past that security - our job is to make it inconvenient, which we did, but we have to plan for them to bypass it. We can do that by limiting what data the server sends to the client. In my example Iâm making sure the user is logged in, and then making sure they are not a âdeactivatedâ role, but in your case you can edit as you like:
Meteor.publish(âsuppliersâ, function() {
// if user is not logged in, do not return anything
if(!this.userId)
return null;
// if user is deactivated, do not return anything
if (Roles.userIsInRole(this.userId, ['deactivated']))
return null;
return SuppliersCollection.find();
});
Method-level: Aside from publications, all functions/API that are ran on the server should also verify role similarly. Example:
// check permissions
if(!Roles.userIsInRole(this.userId, [âsuperadminâ,âadminâ])) {
return {
insufficientPermission: true
}
}
Following these 4 steps should leave your application pretty solid. It will be a real pain for them to bypass the layers of client security, and even if they do, they will not have any data and will not be able to perform any functions, unless they are both logged in & in the proper role to access the data/functionality!
Good luck! =)
You might want to look into Meteor Candy, it might be the most âmodernâ way to build admin panels. It sits right in your app, so you can leverage your existing login session and even roles system. A big part of what makes this approach reasonable is dynamic imports, which keeps the package from adding significant weight to the client.