0

I'm working on a project which has several views, which some of the views may not be accessible to a given user. What I want to do is that, if a user navigates to a url that is restricted (due to his permissions), lets say '/project/manhatten/security' I want to display a view (an html partial) which simply says 'Access Denied'.

But I want to display the view without changing the url. I want the url to stay '/project/manhatten/security', so the user can copy the url and give it to someone with enough permission, and it would work fine.

What is the best way to achieve this ? Can I still use ng-view or a combination of ng-view and ng-include ?

Thanks in Advance.

1
  • Well check on server side if he has access to this view. If not for the ng-view call return the content for not found partial. Commented Oct 28, 2013 at 13:05

1 Answer 1

3

I don't know of a way on how to restrict access to a specific view in angular. I think you shouldn't restrict views. What you should do is restrict access to your api. So if a user doesn't have the privilege to delete a project. Simply send a 401 from the server when he calls the api. On the client side handle this 401 in angular with an $http interceptor.

I would do the following:

In your index.html create an element/directive to display the error message

index.html

  <div ng-controller=ErrorMessageCtrl ng-show=error.message>
    {{error.message}}

  <ng-view></ng-view>

The ErrorMessageCtrl will get notified when an access denied error occured:

.controller('ErrorMessageCtrl', function ($scope) {
  $scope.error = {}
  $scope.$on('error:accessDenied', function(event, message) {
    $scope.error.message = message
  })
})

Create an interceptor service to handle http 401 auth error:

.factory('authErrorInterceptor', function ($q, $rootScope) {
  return {
    response: function (response) {
      return response
    },
    responseError: function(rejection) {
      if (rejection.status === 401) {
        $rootScope.$broadcast('error:accessDenied', 'Access Denied')
      }
      return $q.reject(rejection)
    }
  }
})

add the interceptor service to $httpProvider

.config(function ($httpProvider, $routeProvider) {
  $httpProvider.interceptors.push('authErrorInterceptor')
  $routeProvider.when('/project/manhatten/security', {
    template: '<div><h1>Secure Page</h1>secure data from server: {{data}}</div>',
    controller: 'SecureDataCtrl'
  })
})

$http.get('/api/some/secure/data') returns a 401 http status code

.controller('SecureDataCtrl', function ($scope, $http) {
  $scope.data = 'none'
  $http.get('/project/manhatten/security')
    .success(function (data) {
      $scope.data = 'secure data'
    })
})

Please keep in mind that this was hacked in 10 minutes. You need to do some refactoring. Like creating an errorMessage directive which gets the error notification service injected and not broadcasting the error message to the scope.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.