Meteor User profile undefined error during iron router's logout - meteor

I'm using Meteor.user().profile in helper. When i do logout, i gets error profile undefined. My code below:
Template.listedWork.helpers({
workList: function() {
if (Meteor.user().profile.yetki == 1) {
return Work.find({})
} else {
return Work.find({
username: Meteor.user().username
});
}
}
});
I'm doing logout in listedWork page for example: localhost/listedWork. That is iron router render code
Router.route('/listedWork', {
action: function() {
this.render('listedWork');
},
onBeforeAction: function() {
if (!Meteor.userId()) {
this.layout("loginLayout");
this.render('login');
} else {
this.next();
}
}
});
When i logout here, Meteor.user().profile is call by workList that's why i get this error.
login template render in onBeforeAction for logout. Why listedWork template helper call this here.
Thank you for all helps.

The reason Meteor.user().profile is undefined after logout is because you no longer have a Meteor.user(). You need to check for this in your helper and do an appropriate action if Meteor.user() returns null.
Template.listedWork.helpers({
workList() {
if( !Meteor.user() ) {
// Handle the case. Redirect to /login or something.
}
else {
// Your current helper code here.
}
}
});

Related

Password Reset token is returning null, although defined

I'm utilizing useraccounts:unstyled, accounts-base, accounts-password and trying to implement a password resetting feature.
I have my route defined as such:
FlowRouter.route('/reset-password/:token', {
name: 'reset-password',
onBeforeAction: function()
Accounts._resetPasswordToken = this.params.token;
this.next();
},
action(params){
Accounts._resetPasswordToken = params.token;
mount(MainLayout, {
content: (<ForgotPassword />)
});
}
});
My template defined as such:
<template name="ForgotPasswordModal">
{{#if $not currentUser}}
<div class="forgot-modal {{$.Session.get 'nav-toggle'}}" id="{{checkState}}">
<i class="fa fa-close resetPwd"></i>
{{> atForm}}
</div>
{{/if}}
</template>
And my helper functions defined as:
if (Meteor.isClient) {
Template.ForgotPasswordModal.onCreated(function(){
if(Accounts._resetPasswordToken){
Session.set('resetPasswordToken', Accounts._resetPasswordToken);
}else{
console.log("else");
}
});
Template.ForgotPasswordModal.helpers({
checkState() {
return (AccountsTemplates.getState() == 'resetPwd') ? 'forgot-modal' : '';
}
});
Template.ForgotPasswordModal.events({
"submit .at-btn": (event)=>{
event.preventDefault();
console.log(event);
password = document.getElementById('reset-password-new-password').value;
console.log("password", password);
if(password){
Accounts.resetPassword(Session.get('resetPasswordToken'), password, (error)=>{
if(error){
console.log("error: ", error);
}else{
console.log("success");
Session.set('resetPasswordToken', null);
}
});
}
}
});
}
Upon clicking submit I get Error: Match error: Expected string, got null (unknown).
Although if I load the route up (with a valid token) and run Session.get('resetPasswordToken') the token is returned validly.
I was getting this for a few days, couldn't figure it out... then after some rearrangement it finally worked.
And you don't have to use Meteor's default route & form for resetting the password.
You're close #Sleep Deprived Bulbasaur, your route should look like this:
FlowRouter.route('/reset-password/:token', {
name: 'reset-password',
action(params){
Session.set('_resetPasswordToken', params.token);
mount(MainLayout, {
content: (<ForgotPassword />)
});
}
});
I did not need the onBeforeAction, Accounts._resetPasswordToken, or this.next(), and it works just fine and logs you in automatically.
Your template should have something like this:
if (!validateForm(password,passwordAgain)) {
console.log('Your passwords dont match');
} else if (!isValidPassword(password, passwordAgain)) {
console.log('You do not have valid passwords');
} else {
let token = Session.get('_resetPasswordToken');
Accounts.resetPassword(token, password, function(err) {
check(token, String);
if (err) {
console.log('We are sorry but something went wrong.');
} else {
console.log('Your password has been changed. Welcome back!');
}
});
}
Please try using this way:
FlowRouter.route('/#/reset-password/:token');
This is default route for reset Password.

what is the difference of subscribing collection under waitOn , subscriptions and onBeforeAction

I would like to the difference if any in the following ways of subscribing data,
using waitOn
waitOn:function(){
Meteor.subscribe('//some published function)
}
using onBeforeAction
Router.onBeforeAction : function(){
Meteor.subscribe('//some published function)
}
using subscriptions
subscriptions: function() {
this.subscribe('items');
}
If you want to publish data only for authorized users, it is possible that you check (if user is authenticated) for a route, in onBeforeAction. Something like:
Router.map(function(){
this.route('home', {
path : '/',
template : 'home'
});
this.route('register', {
path : '/register',
template : 'register'
});
this.route('login', {
path : '/login',
template : 'login'
});
this.route('requestlisting', {
path : '/requestlisting',
template : 'requestlisting',
waitOn : function(){
return Meteor.subscribe('RequestsPublication');
}
});
...
});
var requireLogin = function () {
if(!Meteor.user()){
if(Meteor.loggingIn()){
this.render(this.loadingTemplate);
}else{
Router.go('login');
}
} else {
this.next();
}
}
Router.onBeforeAction(requireLogin, {only: ['requestlisting',...]});
In this example, in onBeforeAction, routing occurs for 'requestlisting' only if a user logged in, after then it makes sense to subscribe to any data.

Iron Router OnBefore Hook with Params URL Not Calling Function

I am looking to restrict access to a page using iron router, but the before function doesn't seem to be running.
# Limit which challenges can seen to members.
isMemberHook = () ->
challenge = Challenges.findOne _id: #params._id
if Meteor.userId() in challenge.members
#next()
else
#redirect '/'
Router.onBeforeAction isMemberHook,
only: ['/challenge/:_id']
Turns out that for routes with "/" you need to use ".".
So in this case I used:
only: ["challenge.:_id"]
Problem solved!
You have to be careful to account for when a user is logged in, not logged in, and when they are logging in.
The following is code for a requireLogin function that I place in a onBeforeAction hook.
If there's no Meteor user, check to see if they're logging in, and if so, render a loading template.
var requireLogin = function() {
if (! Meteor.user()) {
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
this.render('AdminLogin');
}
} else {
this.next();
}
};
Router.onBeforeAction(requireLogin, {only: ['AdminMain', 'postSubmit', 'appointmentsList', 'AppointmentShow']});
EDIT
Ok, this is what's happening:
https://github.com/iron-meteor/iron-router/blob/devel/Guide.md#applying-hooks-to-specific-routes
What's not perfectly clear from the documentation is what kind of arguments the array takes in the onBeforeAction
Router.onBeforeAction(requireLogin, {only: ['routeName', 'anotherRouteName']});
Here's a set of routes that work with the hook:
this.route('/order', {
template: 'order',
name: 'order',
layoutTemplate: 'layout'
});
this.route('/order/:_id', {
template: 'order',
name: 'orderEdit',
layoutTemplate: 'layout',
data: function(){
var id = this.params._id;
alert(id);
}
});
var beforeHook = function(){
console.log("beforeHook run!");
alert("safsf");
};
Router.onBeforeAction(beforeHook, {only: ['orderEdit']});

iron-router except fails?

So i'm just getting started with iron-router, and I've been building a login system. It works via a .onBeforeAction hook before every route, checking if the user is logged in. However, there are a few routes I want public, so I've added an except option, as per the docs. Except the problem is it doesn't work :( can anybody see why?
Router.route('/new', function () {
name: 'new',
this.render('newComp');
});
Router.route('/c/:_id', {
name: 'compPage',
data: function() { return Comps.findOne(this.params._id); }
});
Router.route('/c/:_id/embed', function () {
name: 'embed',
this.layout('empty'),
this.render('compEmbed', {
data: function () {
return Comps.findOne({_id: this.params._id});
}
});
});
function loginFunction(){
// all properties available in the route function
// are also available here such as this.params
if (!Meteor.user()) {
// if the user is not logged in, render the Login template
if (Meteor.loggingIn()) {
this.render(this.loadingTemplate);
} else {
this.layout('empty');
this.render('login');
}
} else {
// otherwise don't hold up the rest of hooks or our route/action function
this.next();
}
}
Router.onBeforeAction( loginFunction, {
except: ['embed'] // this aint working
});
The problem seems to be in your route definition, the name param should be in the third param of Router.route(), like this (so your route actually didn't have a name, thus the except:['route.name'] doesn't work):
Router.route('/c/:_id/embed', function () {
this.layout('empty'),
this.render('compEmbed', {
data: function () {
return Comps.findOne({_id: this.params._id});
}
});
}, {
name: 'embed',
});
More info about named routes here: http://eventedmind.github.io/iron-router/#named-routes

Do Meteor-Roles and Iron-Router play nicely together?

I have a Meteor app with an editor page that should only be accessible to editors. I am using Iron-Router and my Router.map looks like the following. However, this is not working in an odd way. If I provide a link to the editor page, then all is well, but if I try entering the /editor url, then it always redirects to home, even if the user role is correctly set.
(One thing I ruled out was if Meteor.userId() is not set before Roles.userIsInRole is called in before.)
Anyone know why this would be?
Router.map(function() {
...
this.route('editor', {
path: '/editor',
waitOn: function() {
//handle subscriptions
},
data: function() {
//handle data
},
before: function() {
if ( !Roles.userIsInRole(Meteor.userId(), 'editor') ) {
this.redirect('home');
}
}
});
...
});
The Roles package sets up an automatic publication that sends the roles property on the Meteor.users collection. Unfortunately, you can't get a subscription handle for automatic publications, so you'll need to make your own.
Set up a new subscription that publishes the required data of a user, then configure Router to check that the data is ready before showing any page.
eg:
if (Meteor.isServer) {
Meteor.publish("user", function() {
return Meteor.users.find({
_id: this.userId
}, {
fields: {
roles: true
}
});
});
}
if (Meteor.isClient) {
var userData = Meteor.subscribe("user");
Router.before(function() {
if (Meteor.userId() == null) {
this.redirect('login');
return;
}
if (!userData.ready()) {
this.render('logingInLoading');
this.stop();
return;
}
this.next(); // Needed for iron:router v1+
}, {
// be sure to exclude the pages where you don't want this check!
except: ['register', 'login', 'reset-password']
});
}

Resources