Implementing secure pages and $rootScope is not defined - javascript

Inside my angularjs app. I have userService which has method for determination if user is loggedIn or not. userService.user.loggedIn()
now I want to use that service in order to implement secure pages, where I will redirect user upon this userService.user.loggedIn() statement.
my app.js looks like this
(function () {
"use strict";
var app = angular.module("myApp",
["common.services",
"$rootScope",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"]);
app.config(["$stateProvider", "$urlRouterProvider",
function ($stateProvider, $urlRouterProvider, $rootScope) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("index", {
url: "/",
templateUrl: "app/index.html",
})
// Home page /* SECURED */
.state("home", {
url: "/home",
templateUrl: "app/home/home.html",
controller: "HomeController as vm",
data: {
requiresLogin: true
}
})
// Login
.state("login", {
url: "/login",
templateUrl: "app/login/login.html",
controller: "LoginController as vm"
})
}]
);
$rootScope.$on('$stateChangeStart', function (e, to, userService) {
if (to.data && to.data.requiresLogin) {
if (!userService.user.loggedIn()) {
//token not found/not valid
e.preventDefault();
$location.path('/login');
}
}
});
}());
Inside console I'm getting
ReferenceError: $rootScope is not defined
$rootScope.$on('$stateChangeStart', function (e, to, appUserService,
$rootScope)...

It's not in the array of injectable:
Try this:
app.config(["$stateProvider", "$urlRouterProvider", "$rootScope",
function ($stateProvider, $urlRouterProvider, $rootScope) {

You can only place providers in config. So place your $rootScope.$on function in app controller.

Related

Redirecting state: null is not an object (evaluating 'name')

When a user enters the state cloud, it checks if a current variable is found, and if it isn't, it redirects them to a different state. But for some reason, I get the following error on the redirect.
If I just go directly to /new, it does not give me the error. Only when the redirect occurs.
Does anyone know what the issue might be?
.config(function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/cloud');
var billable = ['$rootScope', '$state', function ($rootScope, $state) {
if(!$rootScope.billable) $state.go('new');
}];
$stateProvider
.state('new', {
url: '/new',
views: { 'main': { templateUrl: 'pages/templates/new.html', controller: 'new' } },
})
.state('cloud', {
url: '/cloud',
views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } },
onEnter: billable
})
})
Error: null is not an object (evaluating 'name')
updateView#http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3953:87
http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3924:21
$broadcast#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:14720:33
load#http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3678:32
http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3554:30
proceed#http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:474:48
invoke#http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:470:33
http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:449:20
http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3557:46
forEach#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:331:24
resolveViews#http://cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.js:3551:16
processQueue#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:13189:29
http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:13205:39
$digest#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:14217:36
http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:14440:33
completeOutstandingRequest#http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:4905:15
http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.js:5285:33
The way you have this configured, I don't believe any states have been defined yet because the application has not yet been bootstrapped. Additionally, route redirects like this are typically placed in the run method, not in the config.
You could pass billable (as a boolean or whatever you need it to be) in the params of the url and redirect based on that.
i.e.
// I'm assuming you're using UI-Router
.config(['$stateProvider', '$urlRouterProvider', '$locationProvider', function($stateProvider, $urlRouterProvider, $locationProvider) {
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise('/cloud');
$stateProvider
.state('new', {
url: '/new',
views: { 'main': { templateUrl: 'pages/templates/new.html', controller: 'new' } },
})
.state('cloud', {
url: '/cloud?billable',
views: { 'main': { templateUrl: 'pages/templates/cloud.html', controller: 'cloud' } },
})
}])
.run(['$rootScope', '$state', function($rootScope, $state) {
$rootScope.$on("$stateChangeStart", function(e, toState, toParams, fromState, fromParams) {
if (!toParams.billable) {
e.preventDefault();
$state.go('new');
}
});
}]);

using auth header to prevent access to page

On login action I'm storing inside localstorage username and token for logged user where afterwards I'm creating auth. headers that post request.
Update:
to be more specific on this. I have userService which succ. put and retrieve users data from the localstorage, where I have username, sessionId, and isLogged.
My question is: Now having Auth. header, all info I need about logged user inside localstorage, how can I write an event handler to check if the user is logged in before each route change.
Should I do that on app.js where I init my app and to inject userService? if yes how.
(function () {
"use strict";
var app = angular.module("myApp",
["common.services",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"]);
....
How can I now use this stored auth header in order to access/deny
access to specific pages?
Update 2: app.js
(function () {
"use strict";
var app = angular.module("myApp",
["common.services",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"]);
app.config(["$stateProvider", "$urlRouterProvider",
function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("index", {
url: "/",
templateUrl: "app/index.html",
})
// Restricted
.state("home", {
url: "/home",
templateUrl: "app/home/home.html",
controller: "HomeController as vm"
})
}]
);
}());
i think that the right approach to your problem is to use resolve property in the route, so the user can't navigate to certain pages if he isn't logged in and once he logged in you can inject the user object to the controller
for example to navigate to home page you must be logged in
.when("/home", {
templateUrl: "homeView.html",
controller: "homeController",
resolve: {
user: function(AuthenticationService){
return AuthenticationService.getUser();
}
}
})
app.controller("homeController", function ($scope, user) {
$scope.user = user;
});
good example: https://www.sitepoint.com/implementing-authentication-angular-applications/
You can achieve this by marking required routes with custom attribute and verifying that token is valid when "location" is changing.
Update Assuming you can verify that user is authenticated by checking isLogged property of userService:
(function () {
"use strict";
var app = angular.module("myApp",
["common.services",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"]);
app.config(["$stateProvider", "$urlRouterProvider",
function ($stateProvider, $urlRouterProvider) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("index", {
url: "/",
templateUrl: "app/index.html",
})
// Restricted
.state("home", {
url: "/home",
templateUrl: "app/home/home.html",
controller: "HomeController as vm",
data: {
requiresLogin: true
}
})
}]
).run(['$rootScope', '$state', 'userService', function($rootScope, $state, userService) {
$rootScope.$on('$stateChangeStart', function(e, to) {
if (to.data && to.data.requiresLogin && !userService.isLogged) {
e.preventDefault();
$state.go('index');
}
})
}]);
}());

securing access to url and rootScope undefined

(function () {
"use strict";
var app = angular.module("myApp",
["common.services",
"$rootScope",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"]);
app.config(["$stateProvider", "$urlRouterProvider","$rootScope",
function ($stateProvider, $urlRouterProvider, $rootScope) {
$urlRouterProvider.otherwise("/");
$stateProvider
.state("index", {
url: "/",
templateUrl: "app/index.html",
})
// Home page /* SECURED */
.state("home", {
url: "/home",
templateUrl: "app/home/home.html",
controller: "HomeController as vm",
data: {
requiresLogin: true
}
})
// Login
.state("login", {
url: "/login",
templateUrl: "app/login/login.html",
controller: "LoginController as vm"
})
}]
);
$rootScope.$on('$stateChangeStart', function (e, to, userService) {
if (to.data && to.data.requiresLogin) {
if (!userService.user.loggedIn()) {
//token not found/not valid
e.preventDefault();
$location.path('/login');
}
}
});
}());
You didn't post what the problem is, but I assume it is that nothing works. If so here is obvious problem with your code: you are trying use $rootScope as module dependency to application module.
Correct module definition must be:
angular.module("myApp", [
"common.services",
"ui.router",
"ui.mask",
"userService",
"ui.bootstrap"
])
I removed "$rootScope" from the list.
UPD. Closer look revealed another problem. You can't inject $rootScope into config block. Move it to the run:
app
.config([...])
.run(['$rootScope', function($rootScope) {
$rootScope.$on(...);
}];
you cant inject services (rootScope is service) in config only provides
but you can do it in app.run
Here's the calling order:
app.config() //only provides can be injected
app.run()
directive's compile functions (if they are found in the dom)
app.controller()
directive's link functions (again, if found)
app.run(["$stateProvider","$rootScope","userService",
function($stateProvider,$rootScope,userService){
$rootScope.$on('$stateChangeStart', function (e, toState, toParams, fromState, fromParams) {
if (toState.data && toState.data.requiresLogin) {
if (!userService.user.loggedIn()) {
//token not found/not valid
e.preventDefault();
$location.path('/login');
}
}
});
}]);

Factory and Resource Makes Angular UI Router not Work

I've been following this tutorial https://www.youtube.com/watch?v=X_NZr_-RaLw and in my clientapp.js, when I insert
.factory('UserService', function($resource) {
return $resource('https://troop.tech/api/users/:user', {user: '#user'});
});
Into my code, all the angular UI routing just stops working.
Context:
var myApp = angular.module('myApp', ['ui.router','ngRouter'])
myApp.factory('UserService', function($resource) {
return $resource('https://troop.tech/api/users/:user', {user: '#user'});
});
myApp.config(function($stateProvider, $urlRouterProvider, $httpProvider) {
$urlRouterProvider.otherwise('/dashboard');
$stateProvider
// HOME STATES AND NESTED VIEWS ========================================
.state('home', {
url: '/home',
templateUrl: 'partial-home.html'
})
.state('dashboard', {
url: '/dashboard',
templateUrl: 'partial-dashboard.html'
})
.state('about', {
url: '/about',
templateUrl: 'partial-about.html'
})
.state('register', {
url: '/register',
templateUrl: 'partial-register.html'
});
$httpProvider.interceptors.push('authInterceptor');
});
myApp.controller('userController', function ($scope, $http, $window, UserService) {
$scope.users = UserService.query();
$scope.setDataForUser = function(userID) {
};
$scope.addUser = function(){
};
...
In your factroy you use $resource as a parameter so you need inject angular built in resource liberary.
In index.html:
<script src="yourComponentFolder/angular-resource/angular-resource.js"></script>
And add a module ngResource...
var myApp = angular.module('myApp', ['ui.router','ngRouter','ngResource']);
Reference in your Application that yoy follow
And one thing if you use ui-router not necessary to inject ngRouter so if you can discard ngRouter from module.

ui-router - $state.go() not working

Here is the app.js of my project:
(function () {
'use strict';
angular
.module('app', ['ui.router', 'ngCookies', 'angular-inview', 'ngMaterial'])
.config(config)
.run(run);
config.$inject = ['$stateProvider', '$urlRouterProvider', '$mdThemingProvider'];
function config($stateProvider, $urlRouterProvider, $mdThemingProvider) {
$mdThemingProvider.theme('default')
.primaryPalette('deep-orange')
.accentPalette('teal', {
'default': 'A400'
});
$urlRouterProvider.otherwise('/app');
$stateProvider
.state('app', {
url: '/app',
data: {
clearenceLevel: 1
},
views: {
'': {
templateUrl: 'app/views/navbar.html',
}
}
})
.state('home.works', {
url: '/works',
templateUrl: 'app/views/works.html',
controller: 'WorksController as vm'
})
.state('login', {
url: '/login',
templateUrl: 'app/views/login.html',
controller: 'LoginController as vm',
data: {
clearenceLevel: 0
}
})
.state('register', {
url: '/register',
templateUrl: 'app/views/register.html',
controller: 'RegisterController as vm',
data: {
clearenceLevel: 0
}
});
}
run.$inject = ['$rootScope', '$location', '$state', '$cookieStore', '$http', 'AuthenticationService'];
function run($rootScope, $location, $state, $cookieStore, $http, AuthenticationService) {
$rootScope.globals = $cookieStore.get('globals') || {};
if ($rootScope.globals.currentUser) {
$http.defaults.headers.common['aimm-token'] = $rootScope.globals.currentUser.token;
$http.defaults.headers.common['aimm-id'] = $rootScope.globals.currentUser.id;
}
$rootScope.$on('$stateChangeStart', function (event, toState, toParams, fromState, fromParams) {
var clearenceLevel = toState.data.clearenceLevel;
var loggedIn = $rootScope.globals.currentUser;
if (clearenceLevel > 0 && !loggedIn) {
alert("redirecting");
return $state.go('login');
}
});
}
})();
I just can't have $state.go() working. The $on('$stateChangeStart'...); is working fine, and the alert is poping when trying to reach a protected state with no session. But the return $state.go('login'); doesnt work. It redirects to /app.
Thanks for your help.
Well, thanks to #Vanojx1, I found out adding e.preventDefault(); before the $state.go('login'); made it work. Still dont understand why though.
You need to execute the $state.go on main scope and not in a (angular) service or virtual scope created temporarily.
You can also solve the problem by wrapping it in $timeout or setTimeout which will register it in the browser loop to be executed after the current method run etc even with 0 milliseconds will do it, like.
$timeout(()=>{$state.go('xyz')},0)
or
setTimeout(()=>{$state.go('xyz')},0);

Categories

Resources