Reputation: 449
how would I fetch if the authenticated user has the role admin and use that to prevent access to states in the stateprovider?
node/server.js function to get role from authenticated user:
app.get('/api/isadmin', ensureAuthenticated, function (req, res) {
User.findById(req.user, function (err, user) {
if (req.role !== 'admin') {
return res.status(403).send('Unauthorized');
}
res.send(user);
});
});
And this is where I'm struggling to figure out how to get this to work. I can get the response. I manage to get the role from the current user by using a factory and a controller.
angular.module('App')
.factory('Admin', function ($http) {
$scope.isAdmin = function () {
$http.get('http://localhost:3000/api/isadmin')
.success(function (response) {
return response.data.role;
});
}
});
angular.module('App')
.controller('AdminCtrl', function ($scope, toastr, Admin) {
$scope.getAdmin = function () {
Admin.getAdmin()
.then(function (response) {
$scope.role = response.data.role;
console.log($scope.role);
})
.catch(function (response) {
toastr.error(response.data.message, response.status);
});
};
$scope.getAdmin();
});
My question is how would I get this to happen in app.js so I can append it to states? I have looked at this stack question(Angular ui-router: how to prevent access to a state), but I don't get it to work. I am using satellizer for my authentication bit, it has a $auth.isAuthenticated() function, which I used to try and prevent a state from being accessed from users not authenticated. That didn't work:
.state('profile', {
url: '/profile',
templateUrl: 'Scripts/App/partials/profile.html',
controller: 'ProfileCtrl',
resolve: {
security: ['$q', function ($q, $auth) {
if (!$auth.isAuthenticated()) {
return $q.reject('Not Authorized');
}
}]
}
});
Any help is greatly appreciated.
Upvotes: 0
Views: 1627
Reputation: 313
you can define each state with the user roles who has access and some other types of access like required login etc.
Then in '$stateChangeStart' event you can check all access types as given in example below. I have used the same approach in my last project.
.state('app.view-company-contact', {
cache: false,
url: "/company-contacts/:contact_id",
views: {
'menuContent': {
templateUrl: "templates/company-contact-view.html",
controller: 'ViewCompanyContactCtrl'
}
},
access: {
requiredLogin: true,
requiredRole: ['plus-admin', 'plus-standard', 'basic-admin', 'basic-standard']
}
})
.state('app.messages', {
cache: false,
url: "/messages",
views: {
'menuContent': {
templateUrl: "templates/messages.html",
controller: 'MessagesCtrl'
}
},
access: {
requiredLogin: true,
requiredRole: ['plus-admin', 'plus-standard']
}
})
.run(function($rootScope, $state, Auth){
$rootScope.$on('$stateChangeStart', function (event, toState, toStateParams, fromState, fromStateParams) {
var accessDenied = function(){
event.preventDefault();
//do whatever neccessary
alert("UNAUTHORIZED_ACCESS");
//$state.go("login");
};
if(angular.isDefined(toState.access)){
if(toState.access.requiredLogin && !Auth.isUserLoggedIn()) {
accessDenied();
}else if(toState.access.requiredRole.indexOf(Auth.getLoggedInUserRole()) < 0){
accessDenied();
}else{
//all checks passed
}
}
});
})
Auth is a service with some functions defined like 'isUserLoggedIn()' and 'getLoggedInUserRole()'.
Upvotes: 0
Reputation: 2324
You could add a global event listener on $stateChangeStart
, and check user authorization in its handler, if user is unauthorized, just call event.preventDefault()
to prevent the transition from happening:
angular.module('App').run([
'$rootScope', '$auth', '$state',
function($rootScope, $auth, $state){
$rootScope.$on('$stateChangeStart', function(event, toState){
if(toState.name == 'some states you want to protect'){
if(!$auth.isAuthenticated()){
event.preventDefault();
$state.go('home')
}
}
})
}
])
Upvotes: 1