Skip to content

Instantly share code, notes, and snippets.

@danwit
Created April 26, 2014 00:22
Show Gist options
  • Star 31 You must be signed in to star a gist
  • Fork 7 You must be signed in to fork a gist
  • Save danwit/11307969 to your computer and use it in GitHub Desktop.
Save danwit/11307969 to your computer and use it in GitHub Desktop.
Authorization with node_acl + mongo + express
/**
* Simple node_acl example with mongoDB and expressjs
*
* Usage:
* 1. Start this as server
* 2. Play with the resoures
*
* Show all permissions (as JSON)
* http://localhost:3500/info
*
* Only visible for users and higher
* http://localhost:3500/secret
*
* Only visible for admins
* http://localhost:3500/topsecret
*
* Manage roles
* user is 'bob' and role is either 'guest', 'user' or 'admin'
* http://localhost:3500/allow/:user/:role
* http://localhost:3500/disallow/:user/:role
*
* Don't forget to disallow a role, if you want to revoke its
* permissions.
*/
var mongodb = require( 'mongodb' ),
express = require( 'express' ),
node_acl = require( 'acl' ),
port = 3500,
app = express(),
// The actual acl will reside here
acl;
// Error handling ( most notably 'Insufficient permissions' )
app.use( app.router );
app.use( function( error, request, response, next ) {
if( !error ) return next();
response.send( error.msg, error.errorCode );
});
// Connecting to our mongo database
mongodb.connect( 'mongodb://127.0.0.1:27017/acl_example', _mongo_connected );
function _mongo_connected( error, db ) {
var mongoBackend = new node_acl.mongodbBackend( db /*, {String} prefix */ );
// Create a new access control list by providing the mongo backend
// Also inject a simple logger to provide meaningful output
acl = new node_acl( mongoBackend, logger() );
// Defining roles and routes
set_roles();
set_routes();
}
// This creates a set of roles which have permissions on
// different resources.
function set_roles() {
// Define roles, resources and permissions
acl.allow([
{
roles: 'admin',
allows: [
{ resources: '/secret', permissions: 'create' },
{ resources: '/topsecret', permissions: '*' }
]
}, {
roles: 'user',
allows: [
{ resources: '/secret', permissions: 'get' }
]
}, {
roles: 'guest',
allows: []
}
]);
// Inherit roles
// Every user is allowed to do what guests do
// Every admin is allowed to do what users do
acl.addRoleParents( 'user', 'guest' );
acl.addRoleParents( 'admin', 'user' );
}
// Defining routes ( resources )
function set_routes() {
// Simple overview of granted permissions
app.get( '/info',
function( request, response, next ) {
acl.allowedPermissions( get_user_id(), [ '/info', '/secret', '/topsecret' ], function( error, permissions ){
response.json( permissions );
});
}
);
// Only for users and higher
app.get( '/secret', acl.middleware( 1, get_user_id ),
function( request, response, next ) {
response.send( 'Welcome Sir!' );
}
);
// Only for admins
app.get( '/topsecret', acl.middleware( 1, get_user_id ),
function( request, response, next ) {
response.send( 'Hi Admin!' );
}
);
// Setting a new role
app.get( '/allow/:user/:role', function( request, response, next ) {
acl.addUserRoles( request.params.user, request.params.role );
response.send( request.params.user + ' is a ' + request.params.role );
});
// Unsetting a role
app.get( '/disallow/:user/:role', function( request, response, next ) {
acl.removeUserRoles( request.params.user, request.params.role );
response.send( request.params.user + ' is not a ' + request.params.role + ' anymore.' );
});
}
// Provide logic for getting the logged-in user
// This is a job for your authentication layer
function get_user_id( request, response ) {
return 'bob';
}
// Generic debug logger for node_acl
function logger() {
return {
debug: function( msg ) {
console.log( '-DEBUG-', msg );
}
};
}
// Starting the server
app.listen( port, function() {
console.log( 'ACL example listening on port ' + port );
});
@muratatak77
Copy link

I tried a in express app.
But get some errors

:::::::::::::::::::::::::::::::::::::::::

process.nextTick(function() { throw err; });
^
Error: Callback was already called.
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/acl/node_modules/async/lib/async.js:43:36
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/acl/node_modules/async/lib/async.js:694:17
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/acl/node_modules/async/lib/async.js:173:37
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/acl/lib/mongodb-backend.js:134:18
at handleCallback (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/utils.js:95:12)
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/db.js:845:28
at handleCallback (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/utils.js:95:12)
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/db.js:1538:5
at handleCallback (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/utils.js:95:12)
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/lib/db.js:273:5
at /Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:756:13
at Callbacks.emit (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:95:3)
at null.messageHandler (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/node_modules/mongodb-core/lib/topologies/server.js:243:23)
at Socket. (/Users/muratatak/Documents/project_node/other/acl_test/node_modules/mongodb/node_modules/mongodb-core/lib/connection/connection.js:262:22)
at Socket.emit (events.js:107:17)
at readableAddChunk (_stream_readable.js:163:16)

@scheung38
Copy link

scheung38 commented Dec 20, 2016

Why is get_user_id hard-coded to 'bob'?

function get_user_id( request, response ) {
    return 'bob';
}

Which means both:
http://localhost:3500/disallow/seb/admin
http://localhost:3500/allow/seb/admin

will still return status of bob and not status of seb..

Also:
app.get( '/topsecret'
app.get( '/allow/:user/:role'
app.get( '/disallow/:user/:role'

also wont work too for any user other than 'bob'. Please modify so get_user_id is not returning hard-coded value.

Also why is allowedPermissions' first parameter is get_user_id():

app.get( '/info',
        function( request, response, next ) {
            acl.allowedPermissions( get_user_id(), [ '/info', '/secret', '/topsecret' ], function( error, permissions ){
                response.json( permissions );
            });
        }
    );

But acl.middleware's first parameter is get_user_id (without the parentheses)

    // Only for users and higher
    app.get( '/secret', acl.middleware( 1, get_user_id ),
        function( request, response, next ) {
            response.send( 'Welcome Sir!' );
        }
    ); 

@quandv
Copy link

quandv commented May 3, 2017

Hello! how to check role in view (ejs template engine with node js)?
example:
i have 2 role: view_user and create_user
i want show/hide link for role bellow
if(view_user) -> show: <a href="/user/list">List users</a>
if(create_user) -> show: <a href="/user/create">Create user</a>
Thanks for reply!

@jcmina
Copy link

jcmina commented Jun 21, 2017

This throws an error cannot read property allow..How to overcome this

@Himanshu922
Copy link

Himanshu922 commented Nov 22, 2017

my callback is not getting called..
acl.addUserRoles( "111111", 'user', function(err) {
logger.debug("user added with 'user' role and id");
} );
Same problem in this part also
acl.userRoles('111111', function (err, roles) {
console.log("userROles--", userRoles);
});
plz help

@Gabbar3112
Copy link

how to run this code?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment