Thursday, 15 August 2013

angularjs ui-router authorization before proceeding -



angularjs ui-router authorization before proceeding -

i have angularjs ui-router situation where:

user must authorized before hitting page if user authorized , has no route, redirect homepage if user authorized , has route, redirect route if user authorized , has no route , no homepage, navigate default page if user not authorized , has route, redirect login page , upon authorization redirect route

its tricky situation , can't seem nail right. current code work but... has shows 'login' page split sec before navigating. happens because have kick off $statechangestart somehow.

var app = angular.module('myapp', ['ui.router']); // handle default states based on authentication, // default properties set in user profile, or // or redirect 'apps' page var authd = false, defaultdashboard = undefined, defaultfn = function($injector){ // required location since loaded before app var $location = $injector.get('$location'); // if user has default dashboard, navigate if(defaultdashboard){ $location.path('workspace/' + defaultdashboard); } else if(authd) { // if user auth'd doesn't have url $location.path('home'); } else { // if aren't auth'd yet $location.path('login'); } }; app.config(function ($urlrouterprovider, $locationprovider, $stateprovider) { $locationprovider.html5mode(true); app.stateprovider = $stateprovider; $urlrouterprovider.otherwise(function($injector){ defaultfn($injector); }); }); app.run(function ($rootscope, $q, $location, $state, $stateparams, $injector, security) { var deregister = $rootscope.$on("$statechangestart", function () { // authorize ajax request pass session token , homecoming profile user security.authorize().success(function(d){ // set local flags defaultfn authd = true; defaultdashboard = d.defaultdashboard; // de-register start event after login prevent farther calls deregister(); // switch default view after login if($location.$$url === "/login" || $location.$$url === "/"){ defaultfn($injector); } }).error(function(){ $location.path('login'); }); }); });

i'm using inceptor handle 401s like:

var module = angular.module('security.interceptor', []); // http interceptor listens authentication failures module.factory('securityinterceptor', function($injector, $location) { homecoming function(promise) { // intercept failed requests homecoming promise.then(null, function(originalresponse) { if(originalresponse.status === 401) { $location.path('/login'); } homecoming promise; }); }; }); // have add together interceptor queue string because // interceptor depends upon service instances not available in config block. module.config(function($httpprovider) { $httpprovider.defaults.withcredentials = true; $httpprovider.responseinterceptors.push('securityinterceptor'); });

anyone had similar cases , found improve solution?

heres solution came with:

app.config(function ($urlrouterprovider, $locationprovider, $stateprovider) { $locationprovider.html5mode(true); // placeholder $stateprovider.state('welcome', { url: '/' }); $urlrouterprovider.otherwise('404'); }); app.run(function ($rootscope, $q, $location, $state, $stateparams, security, $urlrouter) { var deregister = $rootscope.$on("$statechangestart", function (event) { // stop change! event.preventdefault(); security.authorize().success(function(d){ // if don't have previous url if($location.$$url === "/" || $location.$$url === "/login"){ // if user has preset home if(d.defaultdashboard){ $location.path('workspace/' + d.defaultdashboard); } else { $location.path('welcome'); } } else { // if do, go on $urlrouter.sync(); } }).error(function(){ // redirect home $location.path('login'); }); // deregister listener deregister(); }); });

essentially, creating empty route empty route solved problem. interesting.

angularjs angular-ui-router

1 comment: