Reputation: 3433
Implemented the authorization using the POST The problem is when i go to a privileged page say '/admin' it works but when i refresh the page manually, the admin page is redirecting to the '/unauthorized' page
Permissions service
angular.module('myApp')
.factory('PermissionsService', function ($rootScope,$http,CookieService) {
var permissionList;
return {
setPermissions: function(permissions) {
permissionList = permissions;
$rootScope.$broadcast('permissionsChanged')
},
getPermissions: function() {
var roleId = 5
if(CookieService.getLoginStatus())
var roleId = CookieService.getUserData().ROLE_ID;
return $http.post('api/user-permissions', roleId).then(function(result){
return result.data;
});
},
hasPermission: function (permission) {
permission = permission.trim();
return _.some(permissionList, function(item) {
if(_.isString(item.name))
return item.name.trim() === permission
});
}
};
});
hasPermissions directive
angular.module('myApp')
.directive('hasPermission', function(PermissionsService) {
return {
link: function(scope, element, attrs) {
if(!_.isString(attrs.hasPermission))
throw "hasPermission value must be a string";
var value = attrs.hasPermission.trim();
var notPermissionFlag = value[0] === '!';
if(notPermissionFlag) {
value = value.slice(1).trim();
}
function toggleVisibilityBasedOnPermission() {
var hasPermission = PermissionsService.hasPermission(value);
if(hasPermission && !notPermissionFlag || !hasPermission && notPermissionFlag)
element.show();
else
element.hide();
}
toggleVisibilityBasedOnPermission();
scope.$on('permissionsChanged', toggleVisibilityBasedOnPermission);
}
};
});
app.js
var myApp = angular.module('myApp',['ngRoute','ngCookies']);
myApp.config(function ($routeProvider,$httpProvider) {
$routeProvider
.when('/', {
templateUrl: 'app/module/public/index.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/login', {
templateUrl: 'app/module/login/login.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/home', {
templateUrl: 'app/module/home/home.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/register', {
templateUrl: 'app/module/register/register.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.when('/admin', {
templateUrl: 'app/module/admin/admin.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html',
permission: 'admin'
})
.when('/unauthorized', {
templateUrl: 'app/partials/unauthorized.html',
header: 'app/partials/header.html',
footer: 'app/partials/footer.html'
})
.otherwise({redirectTo: '/'});
$httpProvider.responseInterceptors.push('securityInterceptor');
});
myApp.provider('securityInterceptor', function() {
this.$get = function($location, $q) {
return function(promise) {
return promise.then(null, function(response) {
if(response.status === 403 || response.status === 401) {
$location.path('/unauthorized');
}
return $q.reject(response);
});
};
};
});
myApp.run(function($rootScope, $location, $window, $route, $cookieStore, CookieService, PermissionsService) {
PermissionsService.getPermissions().then(function(permissionList){
PermissionsService.setPermissions(permissionList);
});
// Check login status on route change start
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
if(!CookieService.getLoginStatus() && $location.path() != '/register' && $location.path() != '/login') {
$location.path("/");
$rootScope.$broadcast('notloggedin');
}
if(CookieService.getLoginStatus() && $location.path() == '/login') {
$location.path("/home");
}
var permission = next.$$route.permission;
if(_.isString(permission) && !PermissionsService.hasPermission(permission))
$location.path('/unauthorized');
});
// Adds Header and Footer on route change success
$rootScope.$on('$routeChangeSuccess', function (ev, current, prev) {
$rootScope.flexyLayout = function(partialName) { return current.$$route[partialName] };
});
});
CookieService
angular.module('myApp')
.factory('CookieService', function ($rootScope,$http,$cookieStore) {
var cookie = {
data: {
login: false,
user: undefined
},
saveLoginData: function(user) {
cookie.data.login = true;
cookie.data.user = user;
$cookieStore.put('__iQngcon',cookie.data);
},
deleteLoginData: function() {
cookie.data.login = false;
cookie.data.user = undefined;
$cookieStore.put('__iQngcon',cookie.data);
},
getLoginStatus: function() {
if($cookieStore.get('__iQngcon') === undefined)
return cookie.data.login;
return $cookieStore.get('__iQngcon').login;
},
getUserData: function() {
return $cookieStore.get('__iQngcon').user;
}
};
return cookie;
});
It seems like the permissions data are lost on page refresh. Is there any other way i can solve the problem? Or is there any problem with the code??
Upvotes: 1
Views: 2283
Reputation: 3433
Well had to think for some time and made the following change for it to work. It may not be the best practice but ya worked for me. Would appreciate if anyone suggested me a better solution in the comments if found.
myApp.run(function($rootScope, $location, $window, $route, $cookieStore, CookieService, PermissionsService) {
var permChanged = false;
PermissionsService.getPermissions().then(function(permissionList){
PermissionsService.setPermissions(permissionList);
});
// Check login status on route change start
$rootScope.$on( "$routeChangeStart", function(event, next, current) {
console.log('$routeChangeStart');
if(!CookieService.getLoginStatus() && $location.path() != '/register' && $location.path() != '/login') {
$location.path("/");
$rootScope.$broadcast('notloggedin');
}
if(CookieService.getLoginStatus() && $location.path() == '/login') {
$location.path("/home");
}
$rootScope.$on('permissionsChanged', function (ev, current, prev) {
permChanged = true;
});
if(CookieService.getLoginStatus() && permChanged) {
var permission = next.$$route.permission;
if(_.isString(permission) && !PermissionsService.hasPermission(permission))
$location.path('/unauthorized');
}
});
// Adds Header and Footer on route change success
$rootScope.$on('$routeChangeSuccess', function (ev, current, prev) {
$rootScope.flexyLayout = function(partialName) { return current.$$route[partialName] };
});
});
What i did was wait for the permissions to be set and then use the permissionChanged broadcast to set a permChanged variable to true and then combined with if user loggedin status and permchanged had to check the permissions if had
$rootScope.$on('permissionsChanged', function (ev, current, prev) {
permChanged = true;
});
if(CookieService.getLoginStatus() && permChanged) {
var permission = next.$$route.permission;
if(_.isString(permission) && !PermissionsService.hasPermission(permission))
$location.path('/unauthorized');
}
Upvotes: 0
Reputation: 39408
when i refresh the page manually, the admin page is redirecting to the '/unauthorized' page
Isn't that expected behavior? If you reload the page; then all UI state is lost; it is just like shutting down the app and starting from scratch.
It seems like the permissions data are lost on page refresh. Is there any other way i can solve the problem? Or is there any problem with the code??
If you want to be able to retain UI state after a page reload, you'll have to retain the Login information somehow, such as in a browser cookies. When the app loads; check for that cookie value. If it exists, you can load the user info from the database, essentially mirroring a login.
I'd be cautious about storing actual user credentials in a cookie without some type of encryption. One approach I've used is to store a unique user key which can be sent to the DB to load user info. Sometimes this may be a UUID associated with the user, Avoid using an auto-incrementing primary key because that is easy to change to get access to a different user's account.
Upvotes: 3