How to redirect users with unverified emails using

2019-04-16 10:45发布

I am using AngularJS with Meteor and wanted to redirect users with unverified emails to the sign in page. I have created a sign in view in /client/routes.js:

app.config(['$stateProvider', '$urlRouterProvider',
function($stateProvider, $urlRouterProvider){
  $urlRouterProvider.otherwise('/');

  $stateProvider

  .state('signin', {
    url:'/signin',
    views: {
      main: {
        templateUrl: 'client/views/profile/signin.tpl'
      }
    }
  })

Note that there are other states I am not listing for brevity sake.

Now, I want to redirect users to this sign in page if their emails have not been verified. How do I modify the example below from UI-Router FAQs to meet my needs? Other solutions not using the example below are acceptable to me as long as they address the issue at hand.

Example: Uses the data object on the state config to define a rule function that will run logic against the user (here using an example service called $currentUser). The $stateChangeStart handler catches all state transition and performs this rule check before allowing the transition, potentially blocking it and/or redirecting to a different state.

app.config(function($stateProvider) {
  $stateProvider.state('privatePage', {
    data: {
      rule: function(user) {
        // ...
      }
  });
});
app.run(function($rootScope, $state, $currentUser) {
  $rootScope.$on('$stateChangeStart', function(e, to) {
    if (!angular.isFunction(to.data.rule)) return;
    var result = to.data.rule($currentUser);

    if (result && result.to) {
      e.preventDefault();
      // Optionally set option.notify to false if you don't want 
      // to retrigger another $stateChangeStart event
      $state.go(result.to, result.params, {notify: false});
    }
  });
});

2条回答
手持菜刀,她持情操
2楼-- · 2019-04-16 11:03

You can use the resolve functionality provided by angular-ui-router to check email verification of current user before the state is resolved. Here's how the code will look like:

app.config(['$stateProvider', '$urlRouterProvider',
    function($stateProvider, $urlRouterProvider) {

        var isVerified = ['User', '$state', '$q',
            function(User, $state, $q) {
                var d = $q.defer();
                var loginPromise = User.getVerificationStatus();
                loginPromise.then(
                    function(response) {
                        d.resolve(response);
                    },
                    function(error) {
                        $state.go('login');
                    });
                return d.promise;
            }
        ];

        $urlRouterProvider.otherwise('/');

        $stateProvider

            .state('signin', {
                url: '/signin',
                views: {
                    main: {
                        templateUrl: 'client/views/profile/signin.tpl'
                    }
                }
            })
            .state('home', {
                url: '/home',
                views: {
                    main: {
                        templateUrl: 'client/views/profile/home.tpl'
                    }
                },
                resolve: {
                    verified: isVerified
                }
            });
    }
]);

Here home state checks for the verification before resolving. I have injected a service User which will arrange the information whether user is verified or not.

You can add resolve property to only those states where you want to check verification status. In this way this is better than checking on $stateChangeStart event which will be fired every time state changes irrespective of whether this check is needed or not.

Here's the link to the documentation.

查看更多
在下西门庆
3楼-- · 2019-04-16 11:07

The example from the FAQ attempts to create a general way to add a rule to any page. Let's keep it simple:

app.run(function($rootScope, $state, UserService) {
    $rootScope.$on('$stateChangeStart', function(event, toState) {
        // don't check auth on login routes
        if (["signin"].indexOf(toState.name) === -1) {
            if (UserService.doesNotHaveVerifiedEmail()) {
                event.preventDefault();
                $state.go('signin');
                return;
            }
        }
    }
}); 

Anytime a state is loaded and it's not the signin state, you check if the user is verified (depends on your application, here I am injecting a UserService which I assume has knowledge about the user's status) and if not, you prevent that state change and redirect them to the signin page.

查看更多
登录 后发表回答