onBeforeAction: How to Check Email Verified - meteor

I'm trying to check the email is verified on the router within an onBeforeAction hook but it's throwing 2 errors. Do you know how to address both?
Error 1:
Exception in callback of async function: .onBeforeAction#http://localhost:3000/lib/router.js?5f85a874ea86a78deb8c19a394c27e00c5a5f753:34:9
Error 2:
Route dispatch never rendered. Did you forget to call this.next() in an onBeforeAction?
The code:
onBeforeAction: function () {
if (Meteor.user()) {
var user = Meteor.user();
if (!user.emails[0].verified) { // line 34
Router.go('confirmEmail');
} else if (!user.gamertagScanned) {
Router.go('confirmGt');
} else {
this.next();
}
} else {
this.render('aboutUs');
}
},

You shouldn't be doing a Router.go() from within onBeforeAction - I suspect you want this.render('confirmEmail') and this.render('confirmGt') instead.

Related

How to make Route setting after admin to be login in Meteor

I created a collection for adminuser's enter the system.I mean I dont want to use account packet for admin side but I dont know How to make Route setting after admin to be login.I made something but it doesnt work correct,
login.html
Template.login.events({
'click #entre': function (e, template) {
var Username = template.$('#username').val();
var Password = template.$('#password').val();
var getinfo= admin.findOne({});
if (Username == " " || Password == "") {
swal("Error", "All fields must be Completed.", "error");
} else if (getinfo.username== Username && getinfo.password== Password) {
swal("Success", "Welcome admin.", "success");
Session.set("hi", true);
} else {
swal("error", "Login Informations wrong.", "error");
}
}
});
router.js
Router.onBeforeAction(function () {
if (!Session.get("hi")) {
this.render('login');
} else {
this.render('dashboard');
}
});
Router.route('userList', function () {
this.render('userList');
});
Router.route('addnewuser', function () {
this.render('addnewuser');
});
Note:I want to make that when admin to be login,it can reach to all pages userlist,addnewuser etc.
If I understood it properly you want to give admin rights to certain routes of yours. There are several ways to achieve this using iron:router, either by building a Controller or using Filters. I would create an Iron Router Controller to tackle that and attach it to any route that needs that kind of checks. Both Controllers and Filters are actually reusable bits of code which is what we are looking for.
Make sure you add alanning:roles to your packages list (if you haven't already) and add some admin roles to at least one of your Meteor.users() like it's shown here
Building the actual Controllers is easy.
lib/router.js
AdminController = RouteController.extend({
onBeforeAction: function () {
var loggedInUser = Meteor.userId();
if (!!loggedInUser) {
if (!Roles.userIsInRole(loggedInUser, 'admin')) {
// Basic redirect to the homepage
Router.go('homepage');
this.stop();
}
} else {
// Log them in when they are not
Router.go('login');
this.stop();
}
this.next();
}
});
Router.route('/admin', {
name: 'admin',
controller: AdminController,
waitOn: function () {
// return subscriptions here
}
});
Continue to add that to any other routes you like.

object is not a function in iron-router routes at onBeforeAction hook's this.next()

I'm running iron-router 1.0.7, and my onBeforeAction hook is causing an exception. Here's the stack trace:
Exception in callback of async function: TypeError: object is not a function
at Router.onBeforeAction.except (http://localhost:3000/lib/router.js?ebfe803416134e7c5b16265486b3998532289c58:45:8)
at http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1199:36
at _.extend.withValue (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:955:17)
at Router.addHook.hookWithOptions (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1198:27)
at boundNext (http://localhost:3000/packages/iron_middleware-stack.js?0e0f6983a838a6516556b08e62894f89720e2c44:424:31)
at Meteor.bindEnvironment (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:983:22)
at Router.onBeforeAction.only (http://localhost:3000/lib/router.js?ebfe803416134e7c5b16265486b3998532289c58:28:12)
at http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1199:36
at _.extend.withValue (http://localhost:3000/packages/meteor.js?43b7958c1598803e94014f27f5f622b0bddc0aaf:955:17)
at Router.addHook.hookWithOptions (http://localhost:3000/packages/iron_router.js?a427868585af16bb88b7c9996b2449aebb8dbf51:1198:27)
and here are the hooks that are referenced:
Router.onBeforeAction(function () {
//check if it's a logged in user
if (!Meteor.userId()) {
//if they aren't redirect them to login
this.render('login');
} else {
//if they are let them through
this.next();
}
},
//the routes we want this if logged in check for
{only: ['profile', 'logout', 'users']
});
// Redirects users to the survey until they have answered all the questions
Router.onBeforeAction(function() {
Meteor.subscribe('questions');
var answered = getUserAnswers();
var unanswered = Questions.find({ _id: { $nin: answered } }, {sort: {priority: 1}}).count();
if (unanswered && Roles.userIsInRole(Meteor.user(), 'manage-users')) {
this.next();
} else if (unanswered) {
this.redirect('survey');
}
this.next();
},
{except: ['survey', 'passwordReset', 'logout', 'settings', 'login']});
It seems to be the last this.next() that's causing the exception (That's the line referenced in the first line of the trace.), but I can't tell why. If I put a breakpoint on it in DevTools, it runs twice just fine. Then, on the third stop, next is undefined. Any idea why this is happening? The routes still seem to work normally despite the exception.

Meteor Iron Router goes to a route's waitOn first instead of Router.onBeforeAction

I've got the Meteor Roles package and I'm trying to define an admin route:
var requireLogin = function() {
if (! Meteor.user()) {
debugger // #1
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
console.log("no user");
this.render('AdminLogin');
}
} else {
this.next();
}
};
Router.onBeforeAction(requireLogin, {only: ['AdminMain']});
Router.route('/admin', {
name: 'AdminMain',
layoutTemplate: 'AdminLayout',
waitOn: function(){
debugger // #2
return [
Meteor.subscribe("appointments")
]
}
});
I've got this in server/publications:
Meteor.publish('appointments', function() {
if (Roles.userIsInRole(this.userId, ['assistant','admin'])) {
return Appointments.find();
} else {
console.log("no user");
return [];
}
});
The first debugger that gets set off is debugger #2 in the waitOn. Why? I have an OnBeforeAction specified precisely for that route. According to the Iron Router guide, Our onBeforeAction hook function will run before our route function when the user navigates to "/admin". If the user is not logged in, the route function will never get called and the AdminPage will not render to the page.
Well, it certainly looks like the route function is being called before the OnBeforeAction considering that debugger stops first to waitOn for a Meteor subscription. Since this subscription requires an admin user to be logged in on the server, if I press continue on debugger the server console logs "no user" and the loading screen goes on forever and forever. The actual OnBeforeAction function for requireLogin never gets called.
waitOn is called before OnBeforeAction. This behavious is corect. From the iron-router docs:
Another alternative is to use waitOn instead of subscribe. This has the same effect but automatically short-circuits your route action and any before hooks (see below), and renders a loadingTemplate instead.
Source
For handling subscriptions you can use 'subscriptions' option:
Router.route('/post/:_id', {
subscriptions: function() {
// returning a subscription handle or an array of subscription handles
// adds them to the wait list.
return Meteor.subscribe('item', this.params._id);
},
action: function () {
if (this.ready()) {
this.render();
} else {
this.render('Loading');
}
}
});
Source

How to properly replace this.stop() with pause() on Iron Router blaze integration

When I upgrade Iron Router to blaze integration branch, I began receiving this warning:
"You called this.stop() inside a hook or your action function but you should use pause() now instead"
Chrome console --> iron-router.js:2104 --> client/route_controller.js:193 from package
The code is on client:
Router.before(mustBeSignedIn, {except: ['userSignin', 'userSignup', 'home']});
var mustBeSignedIn = function () {
if (!Meteor.user()) {
// render the home template
this.redirect('home');
// stop the rest of the before hooks and the action function
this.stop();
return false;
}
return true;
}
I tried replacing this.stop() with: pause(), Router.pause() and this.pause() but still does not work. Also I haven't found pause function on iron-router package.
How do I properly replace this.stop() with pause()?
Thanks
From what I can tell the pause function is the first parameter your before hook is getting called with. Not in the docs anywhere, but that's what I gathered from the code and it seems to work.
Here's what I use:
var subscribeAllPlanItems = function (pause) {
var planId = this.params._id;
this.subscribe('revenues', planId).wait();
this.subscribe('expenses', planId).wait();
};
var waitForSubscriptions = function (pause) {
if (this.ready()) { //all the subs have come in
//NProgress.done();
setPlan(this.params._id);
} else { //all subscriptions aren't yet ready, keep waiting
//NProgress.start();
pause();
}
};
Router.map(function () {
this.route('calendar', {
path: '/calendar/:_id',
template: 'calendar',
before: [
subscribeAllPlanItems,
waitForSubscriptions
],
});
//Other routes omitted
});
var requireLogin = function (pause) {
if (Meteor.loggingIn()) { //still logging in
pause();
}
if (!Meteor.user()) { //not logged in
this.render('signIn');
pause();
} else { //logged in, life is good
console.log("requireLogin: logged in");
}
};
//This enforces login for all pages except the below ones.
Router.before(requireLogin, {
except: ['landing', 'signUp', 'signIn', 'forgotPassword', 'resetPassword']
});
I opened an issue on Github about this. Here's the response I got:
Oops I may have not changed the redirect method yet. Just use Router.go as it will work fine now. I will change over this.redirect sometime next week or a PR is welcome. Controllers are now automatically stopped if you change routes in a hook. You can pause the current run by calling the pause method which is passed as a parameter to your hooks and action functions.

Redirect after Login using Meteor and Iron Router

I'm using the built in loginButtons options with Meteor and I would like to redirect after a user logs in. Using the built in web snippets means I can't use the callback with Meteor.loginwithPassword and I can't see any hooks inside Iron-Router to do the redirect.
Any suggestions?
Meteor often renders so quickly that the page is being loaded before the user has been defined. You need to use Meteor.loggingIn() to account for the situation in which you are in the process of logging in. This code works for me:
this.route('myAccount', {
path: '/',
onBeforeAction: function () {
if (! Meteor.user()) {
if (!Meteor.loggingIn()) Router.go('login');
}
}
}
This example might be useful
// main route render a template
Router.route('/', function () {
this.render('main');
});
// render login template
Router.route('/login', function () {
this.render('login');
});
// we want to be sure that the user is logging in
// for all routes but login
Router.onBeforeAction(function () {
if (!Meteor.user() && !Meteor.loggingIn()) {
this.redirect('/login');
} else {
// required by Iron to process the route handler
this.next();
}
}, {
except: ['login']
});
// add here other routes
// catchall route
Router.route('/(.*)', function () {
this.redirect('/catchallpage');
});
it should be very easy just add something like:
Tracker.autorun(function() {
var currentRoute = Router.current();
if (currentRoute === null) {
return;
}
if (currentRoute.route.getName() === 'login' && Meteor.user() !== null)
Router.go('WelcomeNewUser');
}
You can also just use the same route with another template in case the user is not logged in.
just something like this:
this.route('myAccount', {
before: function () {
if (!Meteor.user()) {
this.render('login');
this.stop();
}
}
}
There is no magic, just looked into the docs ;)
You can simply use one of your existing routes you have configured in Ireland route
Router.go('/myRouterPathToTemplate')

Resources