1

I am using Node.JS with Express, Angular.JS and the node module connect-roles for ACL. I want to allow a user with user.status of "Platinum" to access "Platinum" but not "Gold" and vice versa.

I have the ACL part working, if I enter /Platinum into the navigation bar I can't access /Gold, but when I try to access /Platinum I only get the template but not the root shell, so what comes up is this:

You made it!
You have the {{status}} status!

If I click on a link in angular to /Platinum, everything works as it should. If I enter any neutral address in the navigation bar, everything works as it should.

This should be an easy fix, but I've not figured it out.

Here is the code that sets up authorizations, I'm pretty sure everything here is okay.

ConnectRoles = require('connect-roles')



var user = new ConnectRoles({
    failureHandler: function(req, res, action){
        var accept = req.headers.accept || '';
        res.status(403);
        if(accept.indexOf('html')) {
            res.render('access-denied', {action: action});
        } else {
            res.send('Access Denied - You don\'t have permission to: ' + action);
        }
    }
});

var app = express();

app.use(user.middleware());

// Setting up user authorizations,
// i.e. if req.user.status = "Platinum", they are given Platinum status

user.use('Platinum', function(req) {
    if (req.user.status == 'Platinum') {
        return true;
    }
});
user.use('Gold', function(req) {
    if (req.user.status == 'Gold') {
        return true;
    }
});
user.use('Admin', function(req) {
    if (req.user.status == 'Admin') {
        return true;
    }
});

That sets up authorizations, now the problem lies below with the routing.

app.post('/login', passport.authenticate('local', 
    { successRedirect: '/', failureRedirect: '/login' }));

app.get('/Platinum', user.is('Platinum'), function(req, res) {

  //Obviously the code below is wrong.
    res.render('templates/support/Platinum');
});

app.get('/Gold', user.is('Gold'), function(req, res) {
    res.render('templates/support/Gold');
});
Les Paul
  • 1,260
  • 5
  • 22
  • 46

1 Answers1

1

The way you are configuring your routes on server side (using express) is not correct. For a single page app like AngularJS, you need to do all of the routing for pages on the client (i.e. in Angular). The server still defines routes for API requests (e.g. getting and posting data) and static resources (index.html, partial HTML files, images, javascript, fonts, etc), though.

Thus the following code is wrong in your server side JS:

app.get('/Platinum', user.is('Platinum'), function(req, res) {

  //Obviously the code below is wrong.
    res.render('templates/support/Platinum');
});

app.get('/Gold', user.is('Gold'), function(req, res) {
    res.render('templates/support/Gold');
});

Just remove those lines.

Instead, you need to define the routes that the server will handle, such as your /login post one first, and how to get static files (I suggest prefixing them all with /pub in the URL). Then you need to do something like the technique in this answer to return your index.html page if no routes are matched.

That way, when a user types http://localhost:port/Gold, express will see there is no route defined for /Gold, so it will return index.html, which will load AngularJS, run your Angular app, which will then look at the URL and see if that matches any of the routes your AngularJS app has configured, and if so, fetch the partial for that page and insert it into your ng-view (if using the core router).

Community
  • 1
  • 1
GregL
  • 37,147
  • 8
  • 62
  • 67
  • I found the beginnings to an answer. I listed the answer below and I will edit as I make more progress, let me know if you think it is a good solution. I gotta give you have the credit, you set me on the right path. – Les Paul Mar 20 '15 at 13:37
  • @minusthebear Are you doing this in addition to what I suggested? The code you posted appears to cause the browser to go to the correct URL after you login. I'm not sure whether that will trigger the AngularJS routing or not. Did it work for you? – GregL Mar 20 '15 at 13:45
  • I edited my solution below more, and once I made two separate index pages (both which utilize the same Angular controllers, templates, etc.) the solution worked perfectly. – Les Paul Mar 20 '15 at 13:48
  • Actually, my app.get solution is not complete. I am now using your method to have the routing being done completely on the Angular side. Will post more results as I make progress. – Les Paul Mar 20 '15 at 13:59
  • Okay, good luck mate. I'm off to bed and won't be able to reply for about 12 hours or so. – GregL Mar 20 '15 at 14:17