I don't know why, the logout button in my Meteor App often fails to callback. the code is simple:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
}
maybe the network's problem? so I added some code to ensure my logout button won't look like frozen:
$scope.logout = function () {
Accounts.logout(function () {
// the code often fails to come here
$state.go('login');
});
$timeout(function () {
$state.go('login');
}, 2000);
}
The redirection to login page succeeded, but because Meteor.userId() still have value, the login page still shows the App user someone is logged on.
I want to know if there is a way to delete Meteor.userId / Meteor.user family even when failed connecting to the server.
I know it is not a complete solution, the App user will probably failed to do the next login at that state, but at least they won't complain the App even cannot logout.
The function you're looking for is Meteor.logout() not Accounts.logout()
Related
I've got some code I want to run after the user verifies their email.
Where would I put that?
The only place I can think is a redirected route, but that's a bit hacky, and relies on the user waiting for the redirect to happen. I'm using iron-router.
This was my first attempt, but the recalculate function is server-side.
AccountsTemplates.configureRoute('verifyEmail', {
redirect: function(){
var user = Meteor.user();
if (user) {
user.recalculateSignUpReputation();
Router.go('home');
}
}
});
Here's a solution observing a cursor but that seems like overkill. I'd prefer an event. Solution #1 didn't work for me.
thanks for the comments. I ended up doing this.
AccountsTemplates.configureRoute('verifyEmail', {
redirect: function(){
var user = Meteor.user();
if (user) {
Meteor.call('recalculateSignUpReputation');
Router.go('home');
}
}
});
It works client side, and makes a call to the server-side code. Not awesome, but works. If you have a different/better way, I'll mark it the correct answer.
I'm trying to show a popup or a template page if user has signed in for the first time after sign up basically allowing them configure some stuff on that page before going to dashboard home, It's only needed for convenience and here is what I got (telescope code)
Router.onBeforeAction(hasCompletedChannels);
hasCompletedChannels: function() {
if(!this.ready()) return;
var user = Meteor.user();
if (user && ! userCompletedChannels(user)){
this.render('connectChannels');
} else {
this.next();
}
}
Which I don't really like because this will always run every time, I want it to run just once, And don't even execute the check function. Is it possible to detect first sign in? (After signup)
I think you could just tie it to the specific route. Right now you're tying it to the Router object (every render forces that check as you point out). So if you define your login function to send someone to a specific route after sign-in, you could just verify on that route.
The function Accounts.onLogin gives you a way to do stuff after the login.
Something like
Router.route('profile', {
path: '/profile',
onBeforeAction: function() {
// Check some stoof
// If first time logged in
// render first time template
// else
// this.next() will render the profile page
},
waitOn: function() {
return [
// some subs
];
},
data: function() {
// some data
}
});
I'm assuming that its going to get routed to a page called profile (seems to make sense). You could check for first time logged in by some attribute you use in the user object and the fields you want filled out and force a render of a different template, or a subtemplate. Check out the Iron Router guide for more ideas on ways to configure it.
Best of luck
I have a /user route set up, which is supposed to render the login template if the current user isn't logged in. The entire router has a waitOn that waits for the currentUser subscription to finish. The problem is that when I go to /user it simply renders the dataNotFound template instead.
Here's the snippets of code that are relevant to this situation. I've been careful to show you them in the order they're defined in my lib/router.js file.
Router.plugin('dataNotFound', {notFoundTemplate: 'notFound'});
Router.onBeforeAction(function () {
console.log(Meteor.userId())
if (!Meteor.userId()) this.render('login');
else this.next();
}, { only: ['user'] });
Router.configure({
waitOn: function () { return Meteor.subscribe('currentUser'); }
});
Router.route('/user', {
name: 'user',
template: 'userView',
data: function () { return Meteor.user(); }
});
That console.log above doesn't even ever fire. It seems to me that since it should be a reactive function that even if initially the dataNotFound is rendered, then soon after that the onBeforeAction should be fired and render the login template, right?
It's very bizarre that your console log doesn't even fire. I have a few ideas, but first want to address the last piece of your question.
The dataNotFound plugin is triggered when the data function fires on your rout. This means it is bypassing your onBeforeAction hook altogether, and not that it isn't getting there.
One thing I can think of that might be worth trying would be wrapping the 'user' route action in a if ( this.ready() ) statement:
edit:
Router.route('user', {
// Your other stuff
action: function() {
if this.ready() {
this.render();
},
The reason I suggest this is just that you are using a waitOn statement, but I'm not 100% sure how that works if you don't have a this.ready() somewhere in your route, because that's what (again, from my reading of the documentation, have not fiddled around with it) tells the router what to wait before executing. Possibly it's not waiting at all right now.
I had a problem with onBeforeAction hook after upgrading from meteor 0.9.1 to 1.
It didnt get fired when it should. Like after I log out, I enter address manually and instead of login page I can see the actual site waiting for data that never comes. onRun hook solved it, but as docs says it gets fired only once.
Router.onRun(function () {
if (!Meteor.userId()) {
this.render('login');
} else {
this.next();
}
}, { only: ['user'] });
Try swapping out Meteor.userId() with Meteor.user() in your if statement. See this link for reference on how to handle checking for the user in a before filter: http://www.manuel-schoebel.com/blog/meteorjs-iron-router-filters-before-and-after-hooks.
I found the issue here.
According to this post, thanks to Steeve Cannon. The problem is on waitOn function.
Probably when you logginOut the subscribe to currentUser will fail, and this will make your app in infinite waiting. onBeforeAction runs after waitOn
You will need to check all variables in you Publish to insure waitOn complete successfully.
Put an if statement inside the waitOn function.
waitOn: function () {
if(Meteor.userId())
return Meteor.subscribe('currentUser');
}
Refer this comment to know why this is happening: https://github.com/iron-meteor/iron-router/issues/1010#issuecomment-72210587
I have just picked up meteor again and a few things have changed since I last worked on my app. I have 1 issue at the moment whereby I want to present a login form if the user is not logged in. Previously I was using:
Deps.autorun(function(){
if(Meteor.userId()==null){
$(window).load(function(){
$('#loginModal').modal('show');
});
}});
Which worked fine. Now, however I get an error:
Meteor.userId can only be invoked in method calls
So, how do I now achieve the above.
Thanks in advance
Adam
Here's what I do: on the server side with iron:router with alanning:roles you can do
this.route('EndUserPage', {
path: '/EndUserPage',
onBeforeAction: function (pause) {
if (!(Meteor.user())) {
console.log("Not logged in");
this.setLayout('LoginForm');
this.render('LoginForm');
} else if (!(Roles.userIsInRole(Meteor.user(), 'admin'))) {
this.redirect("/AdminPage")
} else {
this.render();
}
} });
If you don't have the roles package, you cannot check if it's an admin user, but the redirect to the login page would work as desired.
I am working on project using meteor 0.8.2 and i have added "accounts-ui" and "accounts-password" for login functionality in the project. The login module works perfect. I am curious to know that, How to detect the logout event? Is there any function like,
Template.loginButtons.events({
'click .logout'=function(e)
{
console.log("I logged out!");
}
});
There is no official callback like Meteor.onLogout, but the standard way to handle this is as follow :
In templates :
{{#if currentUser}}
<p>logged in</p>
{{else}}
<p>logged out</p>
{{/if}}
currentUser is a standard Spacebars helper that simply returns the current user, if there is none, it returns a falsy value.
http://docs.meteor.com/#template_currentuser
In javascript :
Deps.autorun(function(computation){
var currentUser=Meteor.user();
if(currentUser){
console.log("logged in");
}
else if(!computation.firstRun){
console.log("logged out");
}
});
We can mirror the tempate code by registering a new Deps.Computation that references Meteor.user() which happens to be a reactive data-source returning the current user.
Whenever this variable change (ie on login/logout) the computation will rerun and we can inject our own custom code to handle login/logout in our webapp.
EDIT : as Neil said, the computation is run immediately following the declaration, in a state where the login resuming process maybe uncomplete resulting in a useless systematic logout detection on app startup, which might be an inconvenience.
We can detect the first run of the computation using the built in firstRun property and execute the logout logic only when it's NOT the first run.
You want watch the reactive function Meteor.userId for changes using Deps.autorun.
var started = false;
Deps.autorun(function () {
if (started && !Meteor.userId())
console.log('I logged out!');
started = true;
});
The function runs once immediately so started prevents that from being interpreted as a logout.