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.
Related
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()
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 want to redirect all users to a home page if they are not logged in. Currently I am doing this:
Router.onBeforeAction(function() {
this.render('loading');
if (! Meteor.userId()) {
this.render('Home');
} else {
this.next();
}
});
Which I saw online, but this seems to be prevent my 'loading' template from ever showing and instead shows the default
Loading...
in the top left of the screen. If I change this.render('Home'); to this.redirect('/') I see the correct loading template. However in the '/' route I call another this.render('Home') which I think then triggers the onBeforeAction again which in turn will redirect to '/' which means you are now in an infinite loop of loading.
So what is the correct way to fix my Router.onBeforeAction to achieve my desried goal of making sure users that are not logged in can only see the Home template no matter what URL they type in and do this without messing up my custom loading template elsewhere on the site?
You need to have two before hooks. One is for 'loading' and one is to check if the user is logged in.
The 'loading' one is linked up to your subscriptions and is usually a preinstalled hook with iron router.
Router.onBeforeAction(function() {
if (! Meteor.userId()) {
this.render('Home');
} else {
this.next();
}
}, {except: ['route_one', 'route_two']});
Router.onBeforeAction('loading');
Your route:
Router.route('/', {
name: 'home',
subscriptions: function() {
//Array of Meteor.subscribe to wait for and display the loading template
return [Meteor.subscribe("a_subscription")]
},
loadingTemplate: 'loading',
action: function() {
this.render("Home_logged_in");
}
});
So here, if Meteor.subscribe("a_subscription") is loading it will display the loading template. If the user is logged in it will display the Home_logged_in template and if not logged in (on any route) the Home template.
You can also set exceptions using the names 'route_one' and 'route_two' for your templates (which you can rename to anything else). I named your home template home. But if you added home to the except list the onBeforeAction would not apply to home.
I use this onBeforeAction hook which redirect to the home page if the user is not logged in:
var userAuthHook = function() {
if (Meteor.userId()) {
//continue to the requested url
this.next();
} else {
//redirect to home
this.redirect('/');
}
};
Router.onBeforeAction(userAuthHook, {
except: ['home']
});
Router.route('/', {
name: 'home'
});
Note that I exclude the home page from the hook in order to avoid redirect loops and that the / route is named "home" to be referred to in the hook exclusions.
This works for me and also allows to use loading templates.
I'm trying to publish all the usernames to the clients, even if not signed in. For that, on the server I have:
Meteor.publish("users", function() {
return Meteor.users.find({}, {fields : { username : 1 } });
});
And on the client:
Meteor.subscribe("users");
However, when I try to access the Meteor.users collection, I find nothing there.
(This is essentially the same as the question here: Listing of all users in the users collection not working first time with meteor js, only without checking the roles for admin first. Still doesn't seem to work..)
I'm probably missing something silly..
I find the same issue, and after doing a research i find this package, i think it may should help you.
Take a look and hope it help you
Update
First move the subscription to the /lib folder, just to make sure its the first thing meteor do when start, also change a little bit the subscription like this on the /lib, folder.
Tracker.autorun(function() {
if(Meteor.isClient) {
if (!Meteor.user()) {
console.log("sorry you need to be logged in to subscribe this collection")
}else{
Meteor.subscribe('users');
}
}
});
For better security we just subscribe to the users collection when the client its logged in
This code outputs all the usernames to the clients, even if not signed in (in this case on /users page):
server/publications.js:
Meteor.publish("userlist", function () {
return Meteor.users.find({},{fields:{username:1}});
});
client/users_list.js:
Template.usersList.helpers({
users: function () {
return Meteor.users.find();
}
});
client/users_list.html:
<template name="usersList">
{{#each users}}
{{username}}
{{/each}}
</template>
lib/router.js (using iron:router package):
Router.route('/users', {
name: 'usersList',
waitOn: function(){
return Meteor.subscribe("userlist");
}
});
Hope it helps.
I'm using meteor-router, and I'd like to redirect a user to /user if he requests / and he is already logged in.
As expected, this just renders the user_index template rather than changing the URL:
Meteor.Router.add
'/': -> if Meteor.userId() then 'user_index' else 'index'
I want to do something like this:
Meteor.Router.add
'/': -> if Meteor.userId() then Meteor.Router.to '/user' else 'index'
update 6/4/14:
This question is no longer relevant, and iron-router should be used instead.
meteor-router is now deprecated. Instead use iron-router which can redirect based on logged in status using:
Router.configure({layoutTemplate: 'mainLayout'});
Router.map(function() {
this.route('splash', {path: '/'});
this.route('home');
});
var mustBeSignedIn = function(pause) {
if (!(Meteor.user() || Meteor.loggingIn())) {
Router.go('splash');
pause();
}
};
var goToDashboard = function(pause) {
if (Meteor.user()) {
Router.go('home');
pause();
}
};
Router.onBeforeAction(mustBeSignedIn, {except: ['splash']});
Router.onBeforeAction(goToDashboard, {only: ['splash']});
Example taken from: Meteor.js - Check logged in status before render
--OR--
Use the accounts-entry package. From their site:
Ensuring signed in users for routes
Use AccountsEntry.signInRequired(this) to require signed in users for
a route. Stick that in your before hook function and it will redirect
to sign in and stop any rendering. Accounts Entry also tracks where
the user was trying to go and will route them back after sign in.
You're looking for a filter -- here is a sample from the docs:
Meteor.Router.filters({
'checkLoggedIn': function(page) {
if (Meteor.loggingIn()) {
return 'loading';
} else if (Meteor.user()) {
return page;
} else {
return 'signin';
}
}
});
// applies to all pages
Meteor.Router.filter('checkLoggedIn');
According to this issue it looks like redirects are not part of meteor-router, and may not be. For now I ended up working around the issue. If the project changes to accommodate redirects I'll update my answer, or someone else can post another answer.
update 1/23/13:
I switched to using mini-pages, which correctly deals with this case and includes a lot of great functionality like layouts.
Meteor Router lets you directly access the response object, so you can just do a 302 redirect. Something like the following will work:
Meteor.Router.add("/test/:_id", (id) ->
this.response.writeHead '302', {'Location': '/blah/' + id}
)
You can do this by using a standard filter and wrapping the redirect in a defer object.
Meteor.Router.filters({
requireLogin: function(page) {
if(! (Meteor.loggingIn()|| Meteor.user()) ){
Meteor.defer(function () {
Meteor.Router.to('/login');
});
}
return page;
}
Meteor.Router.filter('requireLogin', {except: 'login'});