Kuja
Kuja

Reputation: 449

check if the authenticated user has role=admin and prevent access to state ui-router

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

Answers (2)

Mayank Kumar
Mayank Kumar

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

MarkoCen
MarkoCen

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

Related Questions