Angular JS state provider login and registration handling - javascript

I am new to angular js, and I am creating admin panel with angular js but I have issue as follows:
$stateProvider
.state('app', {
url: '',
templateUrl: 'menu/menu.html',
controller: 'menuCntrl',
abstract: true,
authenticate: true
})
.state('dashboard', {
url: "/",
templateUrl: 'dashboard/dashboard.html',
controller: 'DashboardCtrl',
parent: "app",
authenticate: true
})
.state('login', {
url: "/login",
templateUrl: 'dashboard/test.html',
controller: 'LoginCtrl',
authenticate: false
})
$urlRouterProvider.otherwise("/");
this is my current routing now my issue is I need to handle login and registration with it. as like if user is logged in then only user can see the dashboard but I can't understand how to handle it.
$rootScope.$on("$stateChangeStart", function (event, toState, toParams, fromState, fromParams) {
if (toState.authenticate ) {
$state.go("/");
event.preventDefault();
}else{
$state.go("/login");
}
})
this is also I have tried but not worked and also I need to handle registration as well...
can anyone help to figure out what will be best method to handle login and registration before user will redirect to dashboard.
Thanks in advance :)

You need to store some value in localstorage or cookies or session to save user is login or not.
Create a function to check user is loged in or not.
In menu controller check if user is login then fine other wise redirect on login page.
Same in your app config.
if user is login then use this:
$urlRouterProvider.otherwise("/");
other wise if user is not login then use this:
$urlRouterProvider.otherwise("/login");

Related

401 error angular routing

I have been driving myself crazy. Hoping one of you can help me out here...
Let me give you some background:
I have an ASP.NET web app that uses AngularJS.
Here is what my Controller looks like:
public ActionResult Index()
{
return View();
}
Ultimately this loads my HomePage and everything comes up great. However when I click a link for example:
<a ui-sref="core.applications">My Apps</a>
It prompts me to enter in a Username and Password. Even though this should be set for anonymous access.
Now if I open a new tab and go directly to that page for example: http://localhost/#/core/applications this loads just fine.
Looking at my routes:
app.config(function ($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider.otherwise('/core/dashboard');
$stateProvider
.state('core', {
url: '/core',
views: {
'': { templateUrl: 'app/core/views/core.html' },
'sidebar#core': {
templateUrl: 'app/core/views/sidebar.html'
},
'content#core': {
templateUrl: ''
}
}
})
.state('core.dashboard', {
url: '/dashboard',
views: {
'content#core': {
templateUrl: 'app/core/views/dashboard.html'
}
}
})
.state('core.applications', {
url: '/applications',
views: {
'content#core': {
templateUrl: 'app/core/views/applications.html'
}
}
})
});
I do not see what could be blocking it and prompting it to load a Username and Password. Is it something to do with ASP.NET Routing? Please help!
I actually figured out the issue.
The issue was related to the Web API call that I do that I pass security credentials and if the credentials end up being repeated too quickly my system blocks them... (dumb enterprise security guys)
Long story short - check if you are calling a 3rd party service this could prevent you from accessing those pages.

AngularJS routing causing issues with server calls

I am using AngularJS in a nodewebkit application.
I have three views:
Home.html
Conversation.html
Login.html
On login, I am calling
$state.go('home.main');
which calls
$stateProvider.state('home.main', {
url: '/home',
views: {
"mainContent": {
templateUrl: 'views/home.html',
controller: 'loginController'
}
}
}
In main html, I am making a server call (through socket.io) to get all conversations.
Since data is huge, it takes some time to load it and in this time gap i.e. before user gets response from server, If user clicks on Logout, It takes user back to login page.
$scope.logout = function(){
//Logout Logic
$state.go('login');
}
i.e. it calls
$stateProvider.state('login', {
url: '/login',
templateUrl: 'views/login.html',
controller: "loginController"
});
Now When a user is trying to login, server responds to call made for getting conversations allowing user to take him to /home/conv.html.
I don't want to disable Logout button while data is being sent from server to client.
Is there any way on routing from /home to /login, we can cancel all server calls?
I copied the code from https://github.com/angular-ui/ui-router/wiki:
$stateProvider.state("contacts", {
template: '<h1>{{title}}</h1>',
resolve: { title: 'My Contacts' },
controller: function($scope, title){
$scope.title = 'My Contacts';
},
onEnter: function(title){
if(title){ ... do something ... }
},
onExit: function(title){
if(title){ ... do something ... }
}
})
The onExit event will be triggered when you move from home.main to another route. So you should register to handle the event at where you declare the home.main route. In this event, you can cancel all server calls. As you are using socket.io, I suggest you use the function socket.removeAllListeners();

How to disable users from accessing previous page by browser back button after logout in angularjs application?

I have an angularjs web application. I am trying not to allow users to go to previous page using browser back button after logout. I wish to show users a messge like "Please login to continue". I am unable to get any ideas. Please suggest.
You can disable access to previous page using 2 ways:
use $stateChangeStart, this method invoke whenever the state is changed, look for token, if token is not found, redirect user to login.
use resolve: resolve will get call before routing happens for the respective state, so inside resolve
Method1:
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
// check if user is navigating to anypage other than login, if so check for token, if token is not present redirect to login page
});
Method2:
$stateProvider.state("dashboard", {
resolve: {
// check if user is navigating to anypage other than login, if so check for token, if token is not present redirect to login page by using defer
}
})
In this mdn article there's explained how to manipulate the browser history:
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history#Adding_and_modifying_history_entries
On one of my older projects I used this to create a "to previous page" button.
You can implement something similar to have access control over different content. Please be aware that you also have to secure your backend.
Where you define your states for the ui.router, you can add user defined data. For example:
angular.module("app", ['ui.router']).config(['$stateProvider', function($stateProvider){
$stateProvider.state('yourSecureState', {
url: '/secure-state',
templateUrl: '/app/views/secure.html',
controller: 'SecureStateController',
data: {
accessLevel: "secured-feature",
title: 'Secured State'
}
});
}]);
With this additional information, you can check in your authentication service if the required access level is available:
angular.module('app').factory('AuthService', ['$rootScope', function($rootScope){
$rootScope.$on('$stateChangeStart', function (event, nextState) {
if (nextState.data && nextState.data.accessLevel && !service.isAuthorized(nextState.data.accessLevel)) {
event.preventDefault();
alert("Not Authorized");
}
});
var service = {
isAuthorized: function(accessLevel) {
//your code here:
}
};
return service;
}]);
A combination of prevent default and window.history.forward() solved the problem.
$rootScope.$on('$stateChangeStart',
function(event, toState, toParams, fromState, fromParams){
event.preventDefault();
window.history.forward();
});
The idea is event.preventDefault() removes the history stack. So if we have gone from page1 -> page2 -> page3, the preventDefault works only as long as reaching the home page. forward() is needed to keep redirecting to the same page.
The following code disables the browser Back button all over your app:
var allowNav = false;
var checkNav = false;
$rootScope.$on(
'$stateChangeSuccess',
function (event, toState, toStateParams, fromState, fromStateParams) {
allowNav = checkNav;
checkNav = true;
}
);
$rootScope.$on(
'$locationChangeStart',
function (event, next, current) {
// Prevent the browser default action (Going back)
if (checkNav) {
if (!allowNav) {
event.preventDefault();
} else {
allowNav = false;
}
}
}
);
app.config(["$routeProvider", function($routeProvider) {
return $routeProvider.when("/", {
redirectTo: "/login"
}).when("/dashboard", {
templateUrl: "views/dashboard.html"
}).when("/login", {
templateUrl: "views/login.html"
}).when("/pages/openAcc", {
templateUrl: "views/pages/openAcc.html"
}).when("/pages/docUpload", {
templateUrl: "views/pages/docUpload.html"
}).when("/pages/listview", {
templateUrl: "views/pages/listview.html"
}).otherwise({
redirectTo: "/404"
})
}]) .run(function($rootScope, $location) {
$rootScope.$on("$routeChangeStart", function (event, next, current) {
if (!(next.templateUrl == "views/login.html")) {
$location.path("/login");
}
})
})
Let's say when the user is logged in to your app, the system generates an auth-token wich contains data that suggest that the user is authenticated. So since any controller it's executed on page render you just need to put a litle validation for your auth-token. If this token is not there, then redirect to login page. I think, you don't need to block any back button.
// First lines inside your controller.
if (!$tokenManager.getToken()) { // Get token.
$location.path('/login');
}
The flow would be:
The user go to login.html and put its credentials (user/password)
The system validates the credentials and generate an auth-token
The system save the token with lets say: tokenManager.save();
The user is now in welcome.html page.
The user logout from the system.
The system delete the auth-token, let's say: tokenManager.clean();
The user press the back button browser button.
The system try to enter to welcome.html page but it's own controller has the validation.
The user is redirected to login.html

Loading different controllers with the same conditional URL

I'm using MEAN and I'm trying to redirect the user to different pages (different controllers as well) using a conditional URL like www.domain.com/#!/:path
I'll explain myself a little more better.
I've got three different packages (users, organizations and events), but all the packages can be accessed by the same parametrized URL (www.domain.com/#!/:path). Path is a field stored in database and each record belonging to each package has its own path. Path is unique, of course.
What i want to do is to detect if the URL the user is visiting belongs to users, organizations or events, for loading the proper page. For that, I have to query the database for checking if that :path is stored in users, organizations or events model. According to the result of that query, just redirecting to the proper controller/page.
I don't know how to accomplish that exactly in AngularJS side. Any suggestion?
Thanks in advance!
SOLUTION:
Finally, i got it working doing something like this:
// states for my app
$stateProvider
.state('home', {
url: '/',
templateUrl: 'system/views/index.html'
})
.state('entity', {
url: '/:path',
template: 'Loading...',
controller: function ($scope, Global, $http, $state, $stateParams) {
$http({
method: 'GET',
url: '/checkUrl/' + $stateParams.path
})
.then(function (result) {
$scope.global = Global;
// Doing entity information accesible globally
$scope.global.entity = result.data.info;
// Redirecting to the proper controller/template
switch ( result.data.type ) {
case 'users':
$state.go('user', {reload: true});
break;
case 'organizations':
$state.go('organization', {reload: true});
break;
default:
};
});
}
})
.state('user', {
url: '',
templateUrl: 'users/views/index.html'
})
.state('organization', {
url: '',
templateUrl: 'organizations/views/index.html'
});
Through /checkUrl/:path a request is made to server side for checking if :path belongs to users, organizations or events. The response contains the info of that entity and the kind (user, organization, event).
From there, it's just redirecting according to the entity matched.

Getting started with Nested View

I am at a total loss with what's wrong with how I've setup my nested views. What am I doing wrong???
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$stateProvider
.state('main', {
url: '/',
template: '<div><h1>Hello World</h1><div ui-view></div></div>',
controller: 'MainCtrl'
})
.state('main.test', {
template: '<div><h2>I\'m here!</h2></div>',
url: '/here'
});
});
What happens is I go to / and it shows me "Hello World", and then I go to /here and it shows me a blank page. I'm not sure what I'm doing wrong...
You need to omit the preceding / in url:
.state('main.test', {
template: '<div><h2>I\'m here!</h2></div>',
url: 'here'
});
debugging
when clicking on this anchor ui-router navigates to this location: http://localhost:8000//here
<a ui-sref="main.test">test</a>
In your application you can easily check the url of a state
app.run(function($state){
var href = $state.href('main.test');
console.log(href); # '//here'
});
Be sure to set the server to support html5mode
$location documantation
Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links to entry point of your
application (e.g. index.html)

Categories

Resources