FlowRouter redirect if user is logged in and if path is - meteor

I'm using Meteor with FlowRouter and i'm looking for a condition like this:
if the user is logged && if the accessed path is http://x.x.x.x/
then redirect to http://x.x.x.x/clients
My current Routes:
Accounts.onLogin(function(){
FlowRouter.go('clients');
});
Accounts.onLogout(function(){
FlowRouter.go('home')
});
FlowRouter.triggers.enter([function(context, redirect){
if(!Meteor.userId()){
FlowRouter.go('home')
}
}]);
FlowRouter.route('/', {
name: 'home',
action(){
BlazeLayout.render('HomeLayout');
}
});
FlowRouter.route('/clients',{
name: 'clients',
action(){
BlazeLayout.render('MainLayout', {main: 'Clients'});
}
});

if(Meteor.userId() && FlowRouter.getRouteName() === 'route_name'){
FlowRouter.go('/route_name');
}
In flow router docs there are a few was to get the current route if you need to restructure the statement above.
https://github.com/kadirahq/flow-router/blob/master/README.md

I'd say that you just have to change your FlowRouter.route('/'...) configuration a bit:
FlowRouter.route('/', {
triggersEnter: [function(context, redirect) {
if (Meteor.userId()) {
redirect('/clients');
}
}],
name: 'home',
action(){
BlazeLayout.render('HomeLayout');
}
});
So any logged in user that accesses '/' will be redirected to 'clients' - worked fine when I tested it. Here's some background info in the flow router docs: https://github.com/kadirahq/flow-router/blob/master/README.md#redirecting-with-triggers

Related

Redirect to multiple routes based on JWT Claim using vuejs routes

Currently i have the following route
routes.push({
path: "/",
redirect: "/Dashboard"
});
When I login, it will redirect me to the /dashboard screen.
But how can I update the route so that when I log in I can check the claims and then based on the role, redirect to a different view.
I tried the following, this is just sudo code as I cant really get it to work. Also if I can I would like to add an alias. Even if I can get it to work is would this be the correct way of doing it?
routes.push({
path: "/",
alias: "/dashboard", --> This does not seem to work with redirect.
redirect: to => {
getUserType(msalInstance).then(userType => {
if(userType == 'Client'){
return { path: '/clients/2/detail' }
}
else {
return { path: '/dashboard' }
}
});
}
});
and the route for the client-detail looks as follows.
routes.push({
path: "/clients/:id?/detail",
name: "client-detail",
props: true,
meta: {
requiresAuth: true,
layout: simpleLayout,
allowedUsers: clientUserTypes
},
component: loadView("client-detail"),
});
I have looked the the beforeEnter hook but when I add it, it seems to get ignored because the redirect is there.

AUTH_REQUIRED with Firebase

I have two states in my application -- /auth and /masters. the latter is the state where i wld like to direct the user only once he or she has been authenticated.
So, i understand that we can use '$urlRouterProvider.otherwise' to configure a default state in the application to /auth. So the foll is my code:
angular.module('ngClassifieds', ['ngMaterial', 'ui.router', 'firebase'])
.config(function($mdThemingProvider, $stateProvider, $urlRouterProvider) {
$mdThemingProvider
.theme('default')
.primaryPalette('blue-grey')
.accentPalette('orange');
$urlRouterProvider.otherwise('/auth');
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: 'components/auth/auth.tpl.html',
controller: 'authCtrl'
})
$stateProvider
.state('masters', {
url: '/masters',
templateUrl: 'components/classifieds.tpl.html',
controller: 'classifiedsCtrl'
});
});
Now, if i enter, for example, anything other than /masters, i am directed to /auth; however, if i enter /masters, i am not directed to /auth.
i was made to understand that i need to look for AUTH_REQUIRED error in Firebase (https://www.firebase.com/docs/web/libraries/angular/guide/user-auth.html) in order to achieve the desired result. However, i feel i'm punching above my weight in trying to incorporate the functionality. So i'd appreciate if you can provide me some guidane. This is how i have tried to refactor the above code, but it's a mess:
angular.module('ngClassifieds', ['ngMaterial', 'ui.router', 'firebase'])
.run(["$rootScope", "$state", function($rootScope, $state) {
$rootScope.$on("$stateChangeError", function(event, toState, toParams, fromState, fromParams, error) {
// We can catch the error thrown when the $requireAuth promise is rejected
// and redirect the user back to the home page
if (error === "AUTH_REQUIRED") {
$state.go("auth");
}
});
}]);
.config(function($mdThemingProvider, $stateProvider, $urlRouterProvider) {
$mdThemingProvider
.theme('default')
.primaryPalette('blue-grey')
.accentPalette('orange');
$urlRouterProvider.otherwise('/auth');
$stateProvider
.state('auth', {
url: '/auth',
templateUrl: 'components/auth/auth.tpl.html',
controller: 'authCtrl',
resolve: {
// controller will not be loaded until $waitForAuth resolves
// Auth refers to our $firebaseAuth wrapper in the example above
"currentAuth": ["Auth", function(Auth) {
// $waitForAuth returns a promise so the resolve waits for it to complete
return Auth.$waitForAuth();
}]
}
})
$stateProvider
.state('masters', {
url: '/masters',
templateUrl: 'components/classifieds.tpl.html',
controller: 'classifiedsCtrl',
resolve: {
// controller will not be loaded until $requireAuth resolves
// Auth refers to our $firebaseAuth wrapper in the example above
"currentAuth": ["Auth", function(Auth) {
// $requireAuth returns a promise so the resolve waits for it to complete
// If the promise is rejected, it will throw a $stateChangeError (see above)
return Auth.$requireAuth();
}]
}
});
});

Route using wrong controller?

I have 2 controllers (iron-router), one for access bits (login etc.) and one for the logged in area. But for some reason one of my routes is choosing to use the wrong controller, even though I'm explicitly stating which one to use. Here is the code:
// Controllers
AccessController = RouteController.extend({
layoutTemplate: 'AccessMaster',
onBeforeAction: function () {
if (Meteor.user()) { // If user is logged in then take them to the Dashboard
this.redirect('/app/dashboard');
} else {
this.next();
}
}
});
DashboardController = RouteController.extend({
layoutTemplate: 'DashboardMaster',
onBeforeAction: function () {
if (!Meteor.user()) { // If user is not logged in then take them to the login
this.redirect('/app/login');
} else {
this.next();
}
}
});
// Routes
Router.route("/app/signup", {
name: 'Signup',
controller: 'AccessController'
});
Router.route("/app/login", {
name: 'Login',
controller: 'AccessController'
});
Router.route("/app/account", {
name: 'Account',
controller: 'DashboardController',
loadingTemplate: 'Loading',
action: function () {
this.render('Account');
}
});
Router.route("/app/dashboard", {
name: 'Dashboard',
controller: 'DashboardController',
loadingTemplate: 'Loading',
waitOn: function () {
…
},
action: function () {
this.render('Dashboard', {
data: {
…
}
});
}
});
When I visit app/account I'm redirected to app/dashboard, as directed in the AccessController. Why is the app/account route using the wrong controller logic?
Edit: Oddly, if I remove the controller declaration in the offending route (controller: 'DashboardController') then the template loads fine. So it only uses the wrong controller when I ask it to us a controller.
I must be missing something but that's awfully odd.
I think that your problem comes from the fact that you are using Meteor.user() in both controllers, which is the actual user document. And like any other collection it may not be immediately ready when the application starts.
If you add a console.log(Meteor.user()) in your controllers, you will see that it is first briefly undefined before returning the user document.
So the route is using the right controller but Meteor.user() is undefined so you are redirected to /app/login where Meteor.user() (probably ready now) returns the documents so you get redirected to /app/dashboard.
To prevent such behavior I use Meteor.userId() which is always available no matter what. And I only use Meteor.user() when I have first tested that Meteor.userId() returned something and if I need more information about the user.

How do I use the current user's username as a Router parameter in iron:router

I have a 'profile' template where I will display user related stuffs. So I wanna make a route for the template, but in the 'path' I want to dynamically insert the current user's username. Just the way we dynamically change the url with regard to post's id and everything.
Here's the router code block as of now.
Router.map(function() {
this.route('profile', {
path: '/profile', //here instead of 'profile' I wanna dynamically insert the current user's username.
});
});
By the way, I was able to load the user related data's to the said template.
I tried loading the username(/username) to the route path in a trial and error way, but in vain. :(
I guess I'm not very good with Iron Router after all. Please help.
I too was struggling with this one for a while... then I came across this SO answer. In my case, I was doing everything right except for failing to pass the username along with the template pathFor link helper.
For some reason, when using :_id in iron router routes, there's no need to reference it in the pathFor helper. This was the source of my confusion, perhaps others' as well.
Here is sample code of using the username in a path for iron router:
router.js
this.route('/:username', {
name: "dashboard",
waitOn: function() {
return Meteor.subscribe("allUserData");
},
data: function() {
return Meteor.users.findOne();
}
});
publications.js
Meteor.publish("allUserData", function() {
if (this.userId) {
return Meteor.users.find(this.userId)
} else {
this.ready()
}
})
page.html
<a href="{{pathFor 'dashboard' username=username}}">
User Dashboard
</a>
Again, at least in my particular case, I was missing the above username=username.
Have you tried this?
this.route('profile', {
path: '/:username',
data: function() { return Meteor.user().username; }
});
Use router parameters:
Router.map(function() {
this.route('profile', {
path: '/:_username', //dynamic parameter username
data: function() {
//here you will get the username parameter
var username = this.params.username;
return {
user: Meteor.users.find({ username: username }) //you can use user object in template
};
}
});
});
Don't forget the waitOn property on routes. Most of the time it's just the timing that's off, creating a publication for this is the best way to get rid of that issue..
Server side, publications.js:
Meteor.publish('me', function() {
if(!this.userId) return false;
else return Meteor.users.find({_id: this.userId});
});
In one of your Router.map() routes:
this.route('me', {
template: 'profile',
notFoundTemplate: 'profile_not_found',
path: '/profile',
waitOn: function() {
return Meteor.subscribe("me");
},
data: function() {
return Meteor.user();
}
});
Don't forget these configuration bits as well:
// Router config.. pretty self explanatory
Router.configure({
layoutTemplate: 'main',
notFoundTemplate: 'not_found',
loadingTemplate: 'loading'
});
// handle the loading screen
Router.onBeforeAction('loading');
// make sure you define routes here that rely on data to throw back
// 404/not found equivalent pages. e.g. no search results found,
// or in this case profile not found
Router.onBeforeAction('dataNotFound', {only: ['profile']});
and you can use the profile template:
<template name="profile">
Current user Id: {{_id}}
</template>
<template name="profile_not_found">
Profile not found. Are you logged in?
</template>

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