i would like to submit an http request to check if the user is logged in each time a route is changed.
is this possible with the latest version of angular ( 1.4.5 ).
my routes are like this:
// configure routes
app.config(['$routeProvider', function($routeProvider){
$routeProvider
// route for the home page
.when('/', {
templateUrl : 'directives/about.html',
controller : 'mainController'
})
// route for the home page
.when('/login', {
templateUrl : 'directives/login.html',
controller : 'loginContoller'
})
// route for the about page
.when('/about', {
templateUrl : 'directives/about.html',
controller : 'aboutController'
})
// route for the contact page
.when('/contact', {
templateUrl : 'directives/contact.html',
controller : 'contactController'
});
}]);
If you look a the docs you will see what arguments the when() method takes.
The route agument is an object and one property is called resolve.
The resolve property is an map of dependencies that should be resolved.
$routeProvider.when('/', {
templateUrl: 'directives/about.html',
controller: 'mainController',
resolve: {
loginCheck: function (myLoginCheckService) {
return myLoginCheckService();//could return a $q.promise object.
}
}
});
resolve - An optional map of dependencies which should be injected into the controller. If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. If any of the promises are rejected the $routeChangeError event is fired.
AngularJS Docs
Look at the docs for more information.
create a helper method
function auth(configs){
// write your auth code here
return configs;
}
At the router would be like this.
.when('/', auth({
templateUrl : 'directives/about.html',
controller : 'mainController'
}))
Can do it by adding routeChangeStart inside run block of Angularjs
app.run(function($rootScope, $location) {
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
if ($rootScope.loggedInUser == null) {
// no logged user, redirect to /login
if ( next.templateUrl === "partials/login.html") {
} else {
$location.path("/login");
}
}
});
});
Related
Is there any possibility to call "dashboard.html" without using Some text? I wont to call "dashboard.html" from javascript.
app.config(function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'loginRegister.html',
controller : 'loginRegister'
})
.when('/dashboard', {
templateUrl : 'dashboard.html',
controller : 'dashboard'
})
})
app.controller('loginRegister', function($scope, $http) {
$scope.showDashboard = function() {
// CALL dashboard.html FROM HERE
}
})
You can use the location function https://docs.angularjs.org/guide/$location
OR you can use the $window inside AngularJS controller
$window.location.href = '/index.html';
It think you will have a complete response here How to redirect to another page using Angular JS?
this is the code for redirecting in angular js app
$location.path('/dashboard');
I want a route to check and see if a Firebase user is signed in before it redirects someone to the /map.html page.
.when('/map', {
templateUrl: 'views/map.html',
controller: 'MapCtrl',
resolve: {
loggedIn: onlyLoggedIn()
}
});
I have tried using resolve (see code above) but I only get errors from the onlyLoggedIn() function that say "user is not defined". User is defined and if I try to pass in user to the function I get an error "Unknown provider: user"
var onlyLoggedIn = function ($location,$q,user) {
var deferred = $q.defer();
console.log("well: "+user);
if (user) {
console.log("user is signed in ");
deferred.resolve();
} else {
deferred.reject();
$location.url('/signup');
}
return deferred.promise;
};
How should I go about checking if a user is signed in with firebase before routing them to the /map page?
Firebase gives me the user variable and in 'other' places in my app it works, so the problem isn't user not being defined, but my onlyLoggedIn function not "getting" it(?)
Security rules in Firebase can prevent the page from data from being viewed without permission. You need a client-side solution to redirect the page. You do in routes.
This is complete code for the Angular Firebase
This is simple code demonstration. I hope that will work for you.
angular.module('myApp.routes', ['ngRoute', 'simpleLogin'])
.constant('ROUTES', {
'/home': {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl',
resolve: {
// forces the page to wait for this promise to resolve before controller is loaded
// the controller can then inject `user` as a dependency. This could also be done
// in the controller, but this makes things cleaner (controller doesn't need to worry
// about auth status or timing of displaying its UI components)
user: ['simpleLogin', function(simpleLogin) {
return simpleLogin.getUser();
}]
}
},
'/chat': {
templateUrl: 'partials/chat.html',
controller: 'ChatCtrl'
},
'/login': {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
},
'/account': {
templateUrl: 'partials/account.html',
controller: 'AccountCtrl',
// require user to be logged in to view this route
// the whenAuthenticated method below will resolve the current user
// before this controller loads and redirect if necessary
authRequired: true
}
})
/**
* Adds a special `whenAuthenticated` method onto $routeProvider. This special method,
* when called, invokes the requireUser() service (see simpleLogin.js).
*
* The promise either resolves to the authenticated user object and makes it available to
* dependency injection (see AuthCtrl), or rejects the promise if user is not logged in,
* forcing a redirect to the /login page
*/
.config(['$routeProvider', function($routeProvider) {
// credits for this idea: https://groups.google.com/forum/#!msg/angular/dPr9BpIZID0/MgWVluo_Tg8J
// unfortunately, a decorator cannot be use here because they are not applied until after
// the .config calls resolve, so they can't be used during route configuration, so we have
// to hack it directly onto the $routeProvider object
$routeProvider.whenAuthenticated = function(path, route) {
route.resolve = route.resolve || {};
route.resolve.user = ['requireUser', function(requireUser) {
return requireUser();
}];
$routeProvider.when(path, route);
}
}])
// configure views; the authRequired parameter is used for specifying pages
// which should only be available while logged in
.config(['$routeProvider', 'ROUTES', function($routeProvider, ROUTES) {
angular.forEach(ROUTES, function(route, path) {
if( route.authRequired ) {
// adds a {resolve: user: {...}} promise which is rejected if
// the user is not authenticated or fulfills with the user object
// on success (the user object is then available to dependency injection)
$routeProvider.whenAuthenticated(path, route);
}
else {
// all other routes are added normally
$routeProvider.when(path, route);
}
});
// routes which are not in our map are redirected to /home
$routeProvider.otherwise({redirectTo: '/home'});
}])
/**
* Apply some route security. Any route's resolve method can reject the promise with
* { authRequired: true } to force a redirect. This method enforces that and also watches
* for changes in auth status which might require us to navigate away from a path
* that we can no longer view.
*/
.run(['$rootScope', '$location', 'simpleLogin', 'ROUTES', 'loginRedirectPath',
function($rootScope, $location, simpleLogin, ROUTES, loginRedirectPath) {
// watch for login status changes and redirect if appropriate
simpleLogin.watch(check, $rootScope);
// some of our routes may reject resolve promises with the special {authRequired: true} error
// this redirects to the login page whenever that is encountered
$rootScope.$on("$routeChangeError", function(e, next, prev, err) {
if( angular.isObject(err) && err.authRequired ) {
$location.path(loginRedirectPath);
}
});
function check(user) {
if( !user && authRequired($location.path()) ) {
$location.path(loginRedirectPath);
}
}
function authRequired(path) {
return ROUTES.hasOwnProperty(path) && ROUTES[path].authRequired;
}
}
]);
I have found a perfectly working and advanced Angularfire-Seed (that encompasses Simple Login). This framework uses ngRoute and $routeProvider to route the appropriate view and to make sure that certain pages are only shown when the user has logged in.
Now I want to integrate this with the Ionic Framework, such that I have an Ionic App that uses this Authentication system. However, Ionic uses $stateProvider.
My question then becomes: how do I combine these two? I guess one of the two has to go and be replaced by the other. But how do you do this?
Below are the two projects that I want to combine:
1. Angular-Fire Seed using $routeProvider (routes.js)
"use strict";
angular.module('myApp.routes', ['ngRoute', 'simpleLogin'])
.constant('ROUTES', {
'/home': {
templateUrl: 'partials/home.html',
controller: 'HomeCtrl',
resolve: {
// forces the page to wait for this promise to resolve before controller is loaded
// the controller can then inject `user` as a dependency. This could also be done
// in the controller, but this makes things cleaner (controller doesn't need to worry
// about auth status or timing of displaying its UI components)
user: ['simpleLogin', function(simpleLogin) {
return simpleLogin.getUser();
}]
}
},
'/chat': {
templateUrl: 'partials/chat.html',
controller: 'ChatCtrl'
},
'/login': {
templateUrl: 'partials/login.html',
controller: 'LoginCtrl'
},
'/account': {
templateUrl: 'partials/account.html',
controller: 'AccountCtrl',
// require user to be logged in to view this route
// the whenAuthenticated method below will resolve the current user
// before this controller loads and redirect if necessary
authRequired: true
}
})
/**
* Adds a special `whenAuthenticated` method onto $routeProvider. This special method,
* when called, invokes the requireUser() service (see simpleLogin.js).
*
* The promise either resolves to the authenticated user object and makes it available to
* dependency injection (see AuthCtrl), or rejects the promise if user is not logged in,
* forcing a redirect to the /login page
*/
.config(['$routeProvider', function($routeProvider) {
// credits for this idea: https://groups.google.com/forum/#!msg/angular/dPr9BpIZID0/MgWVluo_Tg8J
// unfortunately, a decorator cannot be use here because they are not applied until after
// the .config calls resolve, so they can't be used during route configuration, so we have
// to hack it directly onto the $routeProvider object
$routeProvider.whenAuthenticated = function(path, route) {
route.resolve = route.resolve || {};
route.resolve.user = ['requireUser', function(requireUser) {
return requireUser();
}];
$routeProvider.when(path, route);
}
}])
// configure views; the authRequired parameter is used for specifying pages
// which should only be available while logged in
.config(['$routeProvider', 'ROUTES', function($routeProvider, ROUTES) {
angular.forEach(ROUTES, function(route, path) {
if( route.authRequired ) {
// adds a {resolve: user: {...}} promise which is rejected if
// the user is not authenticated or fulfills with the user object
// on success (the user object is then available to dependency injection)
$routeProvider.whenAuthenticated(path, route);
}
else {
// all other routes are added normally
$routeProvider.when(path, route);
}
});
// routes which are not in our map are redirected to /home
$routeProvider.otherwise({redirectTo: '/home'});
}])
/**
* Apply some route security. Any route's resolve method can reject the promise with
* { authRequired: true } to force a redirect. This method enforces that and also watches
* for changes in auth status which might require us to navigate away from a path
* that we can no longer view.
*/
.run(['$rootScope', '$location', 'simpleLogin', 'ROUTES', 'loginRedirectPath',
function($rootScope, $location, simpleLogin, ROUTES, loginRedirectPath) {
// watch for login status changes and redirect if appropriate
simpleLogin.watch(check, $rootScope);
// some of our routes may reject resolve promises with the special {authRequired: true} error
// this redirects to the login page whenever that is encountered
$rootScope.$on("$routeChangeError", function(e, next, prev, err) {
if( angular.isObject(err) && err.authRequired ) {
$location.path(loginRedirectPath);
}
});
function check(user) {
// used by the changeEmail functionality so the user
// isn't redirected to the login screen while we switch
// out the accounts (see changeEmail.js)
if( $rootScope.authChangeInProgress ) { return; }
if( !user && authRequired($location.path()) ) {
$location.path(loginRedirectPath);
}
}
function authRequired(path) {
return ROUTES.hasOwnProperty(path) && ROUTES[path].authRequired;
}
}
]);
2. Ionic Framework (app.js)
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
// 'starter.services' is found in services.js
// 'starter.controllers' is found in controllers.js
angular.module('starter', ['ionic', 'starter.controllers', 'starter.services', 'ngCordova', 'firebase'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if (window.cordova && window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if (window.StatusBar) {
// org.apache.cordova.statusbar required
StatusBar.styleDefault();
}
});
})
.config(function($stateProvider, $urlRouterProvider) {
// Ionic uses AngularUI Router which uses the concept of states
// Learn more here: https://github.com/angular-ui/ui-router
// Set up the various states which the app can be in.
// Each state's controller can be found in controllers.js
$stateProvider
// setup an abstract state for the tabs directive
.state('tab', {
url: "/tab",
abstract: true,
templateUrl: "templates/tabs.html"
})
// Each tab has its own nav history stack:
.state('tab.chats', {
url: '/chats',
views: {
'tab-chats': {
templateUrl: 'templates/tab-chats.html',
controller: 'ChatsCtrl'
}
}
})
.state('tab.account', {
url: '/account',
views: {
'tab-account': {
templateUrl: 'templates/tab-account.html',
controller: 'AccountCtrl'
}
}
})
.state('tab.login', {
url: '/login',
views: {
'tab-login': {
templateUrl: 'templates/tab-login.html',
controller: 'LoginCtrl'
}
}
});
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
})
Update (16/01/2015, 10.46)
I have tried the following (replacing routeProvider by urlRouterProvider), it didnt work (nothing is showing up)
index.html, included:
<ion-nav-view></ion-nav-view>
routes.js
"use strict";
angular.module('myApp.routes', ['ngRoute', 'simpleLogin'])
.constant('ROUTES', {
'/home': {
templateUrl: 'templates/home.html',
controller: 'HomeCtrl',
resolve: {
// forces the page to wait for this promise to resolve before controller is loaded
// the controller can then inject `user` as a dependency. This could also be done
// in the controller, but this makes things cleaner (controller doesn't need to worry
// about auth status or timing of displaying its UI components)
user: ['simpleLogin', function(simpleLogin) {
return simpleLogin.getUser();
}]
},
authRequired: true
},
'/chat': {
templateUrl: 'templates/chat.html',
controller: 'ChatCtrl',
authRequired: true
},
'/camera': {
templateUrl: 'templates/camera.html',
controller: 'CameraCtrl',
authRequired: true
},
'/login': {
templateUrl: 'templates/login.html',
controller: 'LoginCtrl'
},
'/account': {
templateUrl: 'templates/account.html',
controller: 'AccountCtrl',
// require user to be logged in to view this route
// the whenAuthenticated method below will resolve the current user
// before this controller loads and redirect if necessary
authRequired: true
}
})
/**
* Adds a special `whenAuthenticated` method onto $routeProvider. This special method,
* when called, invokes the requireUser() service (see simpleLogin.js).
*
* The promise either resolves to the authenticated user object and makes it available to
* dependency injection (see AuthCtrl), or rejects the promise if user is not logged in,
* forcing a redirect to the /login page
*/
.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) {
// credits for this idea: https://groups.google.com/forum/#!msg/angular/dPr9BpIZID0/MgWVluo_Tg8J
// unfortunately, a decorator cannot be use here because they are not applied until after
// the .config calls resolve, so they can't be used during route configuration, so we have
// to hack it directly onto the $routeProvider object
$urlRouterProvider.whenAuthenticated = function(path, route) {
route.resolve = route.resolve || {};
route.resolve.user = ['requireUser', function(requireUser) {
return requireUser();
}];
$urlRouterProvider.when(path, route);
}
}])
// configure views; the authRequired parameter is used for specifying pages
// which should only be available while logged in
.config(['$stateProvider', '$urlRouterProvider', 'ROUTES', function($stateProvider, $urlRouterProvider, ROUTES) {
angular.forEach(ROUTES, function(route, path) {
if( route.authRequired ) {
// adds a {resolve: user: {...}} promise which is rejected if
// the user is not authenticated or fulfills with the user object
// on success (the user object is then available to dependency injection)
$urlRouterProvider.whenAuthenticated(path, route);
}
else {
// all other routes are added normally
$urlRouterProvider.when(path, route);
}
});
// routes which are not in our map are redirected to /home
// if none of the above states are matched, use this as the fallback
$urlRouterProvider.otherwise('/tab/dash');
}])
/**
* Apply some route security. Any route's resolve method can reject the promise with
* { authRequired: true } to force a redirect. This method enforces that and also watches
* for changes in auth status which might require us to navigate away from a path
* that we can no longer view.
*/
.run(['$rootScope', '$location', 'simpleLogin', 'ROUTES', 'loginRedirectPath',
function($rootScope, $location, simpleLogin, ROUTES, loginRedirectPath) {
// watch for login status changes and redirect if appropriate
simpleLogin.watch(check, $rootScope);
// some of our routes may reject resolve promises with the special {authRequired: true} error
// this redirects to the login page whenever that is encountered
$rootScope.$on("$stateChangeError", function(e, next, prev, err) {
if( angular.isObject(err) && err.authRequired ) {
$location.path(loginRedirectPath);
}
});
function check(user) {
// used by the changeEmail functionality so the user
// isn't redirected to the login screen while we switch
// out the accounts (see changeEmail.js)
if( $rootScope.authChangeInProgress ) { return; }
if( !user && authRequired($location.path()) ) {
$location.path(loginRedirectPath);
}
}
function authRequired(path) {
return ROUTES.hasOwnProperty(path) && ROUTES[path].authRequired;
}
}
]);
I got a routeProvider for my states.
$routeProvider.
when("/register",{
templateUrl: "templates/register.html",
controller: "RegisterCtrl",
resolve: {
user: function(Auth) {
return Auth.resolveUser();
}
}
}).
when("/home",{
templateUrl: "templates/home.html",
controller: "HomeCtrl",
resolve: {
user: function(Auth) {
return Auth.resolveUser();
}
}
}). .... [.....]
Every state got a promise which resolves, when user-state is loggedIn. Then the code of the different controllers is executed. Now I want to have a mainController for the navigation bar, which should be present on all sites. The controller needs the userdata for checking for new messages etc.
Now: how is it possible to define the resolve globally in a root state (so i can access the userdata in the root controller for all sites) and all the other controllers execute their code only, if the promise from this roote state is resolved?
I hope I formulated my question understandable...
I think you're looking for something like $routeChangeStart, that is a way to execute something you want everytime the user changes his route inside your web app. Take a look at Route and this other question from stackoverflow. Hope it helps.
You can do this by defining your routes outside of the $routeProvider.when statements:
var routes = [
{
url: "/register",
config: {
templateUrl: "templates/register.html",
controller: "RegisterCtrl"
}
},
{
url: "/home",
config: {
templateUrl: "templates/home.html",
controller: "HomeCtrl"
}
}
];
Then iterating through your routes to extend the resolve property before registering them with the $routeProvider:
angular.forEach(routes, function (route) {
var url = route.url;
var routeConfig = route.config;
routeConfig.resolve = angular.extend(routeConfig.resolve || {}, {
// add your global resolves here
user: function(Auth) {
return Auth.resolveUser();
}
});
$routeProvider.when(url, routeConfig);
});
Your Auth.resolveUser() should be responsible for returning the fulfilled promise if it was already resolved previously.
I'm creating a very basic login system with Angular JS. Basically, after a login form is submitted, credentials are checked against a database using PHP and Mysqli. If all is ok, it returns successful and I set a variable like $rootScope.isLoggedIn = true and user details in other similar variables.
Now I'm trying to work out the best way to use resolve with my routes so that only logged in users or users with correct permissions can access a page (including on page reload!)
I just can't get my head around how these resolves work. My routing looks like this so far (the dashboard page needs user to be logged in):
app.config(function($routeProvider) {
$routeProvider
//login
.when('/', {
templateUrl : 'framework/views/login.html',
controller : 'LoginCtrl',
title: 'Admin Login'
})
//dashboard
.when('/dashboard', {
templateUrl : 'framework/views/dashboard.html',
controller : 'DashboardCtrl',
title: 'Dashboard',
resolve: { ? }
})
//catch all redirect
.otherwise({ redirectTo: '/' });
});
Resolve will open your route with a resolved variable (that can be injected into controller) as soon as it gets value (instantly or when returned promise will be resolved). See:
resolve: {
myVar: function(service, $rootScope, etc){
return service.obj; // or primitive, or promise or something else
}
}
.controller('DashboardCtrl', function(myVar){
console.log(myVar); // that service.obj goes here
}
That can't prevent route from loading (as I understand, please correct me if I'm wrong).
For your case it's better to use something like this:
.when('/', {
templateUrl : 'framework/views/login.html',
controller : 'LoginCtrl',
title: 'Admin Login',
authenticate: false
})
.when('/dashboard', {
templateUrl : 'framework/views/dashboard.html',
controller : 'DashboardCtrl',
title: 'Dashboard',
authenticate: true
})
$rootScope.$on("$routeChangeStart", function(event, toState){
if (toState.authenticate && !$rootScope.isLoggedIn){
$location.path('/');
}
});