diff --git a/.travis.yml b/.travis.yml index eb8f422..413e146 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,8 @@ sudo: false language: node_js node_js: + - '5' + - '4' - '3' - '2' - '1' diff --git a/index.js b/index.js index 2f6fb4e..9c0a8c7 100644 --- a/index.js +++ b/index.js @@ -80,6 +80,7 @@ function KoaRoles(options) { this.functionList = []; this.failureHandler = options.failureHandler || defaultFailureHandler; this.userProperty = options.userProperty || 'user'; + this.actionMap = {}; } /** @@ -118,10 +119,23 @@ KoaRoles.prototype.use2 = function (action, fn) { throw new TypeError('action can\'t start with `/`'); } assertFunction(fn); + + var old = this.actionMap[action]; + // create or override + this.actionMap[action] = fn; + + // action fn have already been used, skip + if (old) { + return; + } + + var roles = this; this.use1(function *(act) { + // get fn from actionMap + var fn = roles.actionMap[action]; if (act === action) { if (is.generatorFunction(fn)) { - return yield *fn.call(this); + return yield* fn.call(this); } else { return fn.call(this); } @@ -136,11 +150,11 @@ KoaRoles.prototype.use2 = function (action, fn) { KoaRoles.prototype.can = function (action) { var roles = this; return function *(next) { - if (yield *roles.test(this, action)) { - return yield *next; + if (yield* roles.test(this, action)) { + return yield* next; } if (is.generatorFunction(roles.failureHandler)) { - yield *roles.failureHandler.call(this, action); + yield* roles.failureHandler.call(this, action); } else { roles.failureHandler.call(this, action); } @@ -163,7 +177,7 @@ KoaRoles.prototype.test = function *(ctx, action) { var fn = this.functionList[i]; var vote = null; if (is.generatorFunction(fn)) { - vote = yield *fn.call(ctx, action); + vote = yield* fn.call(ctx, action); } else { vote = fn.call(ctx, action); } @@ -191,13 +205,13 @@ KoaRoles.prototype.middleware = function (options) { } } this.userIs = this.userCan = roleCheck; - yield *next; + yield* next; }; }; function tester(roles, ctx) { return function *(action) { - return yield *roles.test(ctx, action); + return yield* roles.test(ctx, action); }; } diff --git a/test/koa-roles.test.js b/test/koa-roles.test.js index 7b2e911..d6855f9 100644 --- a/test/koa-roles.test.js +++ b/test/koa-roles.test.js @@ -43,6 +43,15 @@ describe('koa-roles.test.js', function () { return this.query.role === 'user'; }); + roles.use('friend', function () { + return this.query.role === 'shaoshuai0102'; + }); + + // override previous friend + roles.use('friend', function () { + return this.query.role === 'bar'; + }); + // default roles.use(function (action) { if (this.query.role === action) { @@ -90,6 +99,10 @@ describe('koa-roles.test.js', function () { this.body = 'page can visit by user or admin, current is ' + this.query.role; }); + app.get('/friend', roles.can('friend'), function *() { + this.body = 'The best friend of foo is ' + this.query.role; + }); + app.get('/any', function *(next) { var isadmin = yield *this.userCan('admin'); if (!isadmin) { @@ -235,4 +248,18 @@ describe('koa-roles.test.js', function () { .post('/profile/1/123?role=other') .expect(404, done); }); + + it('should get /friend 200 for bar', function(done) { + request(app) + .get('/friend?role=bar') + .expect('The best friend of foo is bar') + .expect(200, done); + }); + + it('should get /friend 403 for shaoshuai0102 because of role override', function(done) { + request(app) + .get('/friend?role=shaoshuai0102') + .expect({"message":"Access Denied - You don\'t have permission to: friend"}) + .expect(403, done); + }); });