v0.0.10 Finish Authorization - zhentian-wan/MEANAppsFiles GitHub Wiki

Authorization can protect the page content which certain of users don't have access to.

In the application, we set only 'role: admin' user can access the users list. The other user will get 403 status and redirect to the home page.

Data

            User.create({firstName: 'One', lastName: 'One', username: 'One', salt: salt, hash_pwd: hash, role: 'admin'});
            salt = createSalt();
            hash = hashPwd(salt, 'Ken');
            User.create({firstName: 'Two', lastName: 'Two', username: 'Two', salt: salt, hash_pwd: hash, role: ''});
            salt = createSalt();
            hash = hashPwd(salt, 'Ben');
            User.create({firstName: 'Three', lastName: 'Three', username: 'Three', salt: salt, hash_pwd: hash});

Added three test user, user 'One' has admin role.

Server

config/routes.js: add a middleware to check whether the current user has admin role.

    //protect our server side resource
    app.get('/api/users', auth.requireRole('admin'), function(req, res){
        User.find({}).exec(function(err, collection) {
            res.send(collection);
        })
    });

config/auth.js: Check if the user is not logged in yet or the current user's role is not admin, then send back 403 code. Otherwise, continue to get data.

exports.requireRole = function(role) {
    return function(req, res, next) {
        if(!req.isAuthenticated() || req.user.role.indexOf(role) === -1){
            res.status(403);
            res.end();
        }else{
            next();
        }
    };
};

#Clinet

app.js: we add a route for getting users data:

            .when('/admin/users', {
                templateUrl: '/partials/admin/user_list',
                controller: 'usrListController',
                resolve: userRoleCheck.admin
            })

 ...

        var userRoleCheck = {
            admin: {
                auth: function(loginService) {
                    return loginService.authorizeCurrentUserForRoute('admin');
                }
            }
        };

Here using resolve in the route, because angular will process resolve first before it gets to the controller and template, so if in the resolve we return a reject promise, then it will fire a $routeChangeEorr, in the AppController we can listen to this event.

loginService.js:

    service.authorizeCurrentUserForRoute = function(role)  {

        if(IdentityFactory.isAuthorized(role)){
            return true;
        }else{
            return $q.reject(NOT_AUTHORIZED);
        }
    };

identify.js:

    factory.isAuthorized = function(role) {
        if(factory.currentUser && factory.currentUser.role.indexOf(role) > -1){
            return true;
        }else{
            return false;
        }
    }

UsersController.js:

function usrListController(UserResource) {

    var vm = this;
    vm.users = UserResource.query(); //get all the users
}

angular.module('app')

    .controller('usrListController', usrListController);

mainController.js:

function AppController($rootScope, NOT_AUTHORIZED, $location) {
    $rootScope.$on('$routeChangeError', function(event, current, previous, rejction) {
        if(rejction === NOT_AUTHORIZED){
            $location.path('/');
        }
    })
}