From 09b9a8ccb76d426f8b3e20bc4b4f774f5a25fe61 Mon Sep 17 00:00:00 2001 From: ebarault Date: Tue, 13 Dec 2016 11:19:21 +0100 Subject: [PATCH] testing ctx options injection --- package.json | 13 ++++---- server/boot/authentication.js | 3 +- server/boot/root.js | 3 +- server/boot/zzz-createUser.js | 17 ++++++++++ server/model-config.json | 2 +- server/models/user.js | 61 +++++++++++++++++++++++++++++++++++ server/models/user.json | 37 +++++++++++++++++++++ 7 files changed, 126 insertions(+), 10 deletions(-) create mode 100644 server/boot/zzz-createUser.js create mode 100644 server/models/user.js create mode 100644 server/models/user.json diff --git a/package.json b/package.json index 97e447c..f9a6ccb 100644 --- a/package.json +++ b/package.json @@ -11,17 +11,16 @@ "compression": "^1.0.3", "cors": "^2.5.2", "helmet": "^1.3.0", - "loopback-boot": "^2.6.5", - "loopback-component-explorer": "^2.4.0", + "loopback-boot": "^2.23.0", + "loopback-component-explorer": "^2.7.0", "serve-favicon": "^2.0.1", - "strong-error-handler": "^1.0.1", - "loopback-datasource-juggler": "^2.39.0", - "loopback": "^2.22.0" + "strong-error-handler": "^1.1.1", + "loopback": "git+https://github.com/strongloop/loopback.git#feature/options-from-context-v2" }, "devDependencies": { - "eslint": "^2.13.1", + "eslint": "^3.7.1", "eslint-config-loopback": "^4.0.0", - "nsp": "^2.1.0" + "nsp": "^2.6.2" }, "repository": { "type": "", diff --git a/server/boot/authentication.js b/server/boot/authentication.js index 8e88d4b..193d412 100644 --- a/server/boot/authentication.js +++ b/server/boot/authentication.js @@ -1,6 +1,7 @@ 'use strict'; -module.exports = function enableAuthentication(server) { +module.exports = function enableAuthentication(server, next) { // enable authentication server.enableAuth(); + next(); }; diff --git a/server/boot/root.js b/server/boot/root.js index 6adce90..77d05cf 100644 --- a/server/boot/root.js +++ b/server/boot/root.js @@ -1,8 +1,9 @@ 'use strict'; -module.exports = function(server) { +module.exports = function(server, next) { // Install a `/` route that returns server status var router = server.loopback.Router(); router.get('/', server.loopback.status()); server.use(router); + next(); }; diff --git a/server/boot/zzz-createUser.js b/server/boot/zzz-createUser.js new file mode 100644 index 0000000..ef04c39 --- /dev/null +++ b/server/boot/zzz-createUser.js @@ -0,0 +1,17 @@ +'use strict'; + +module.exports = function(server, next) { + var user = server.models.user; + user.create({email: 'test@test.com', password: 'a1b2c3'}) + .then(function(user) { + return user.accessTokens.create(); + }) + .then(function(token) { + console.log(token); + next(); + }) + .catch(function(err) { + console.log(err); + next(); + }); +}; diff --git a/server/model-config.json b/server/model-config.json index 8a12041..7e98e1b 100644 --- a/server/model-config.json +++ b/server/model-config.json @@ -13,7 +13,7 @@ "./mixins" ] }, - "User": { + "user": { "dataSource": "db" }, "AccessToken": { diff --git a/server/models/user.js b/server/models/user.js new file mode 100644 index 0000000..ae8b03b --- /dev/null +++ b/server/models/user.js @@ -0,0 +1,61 @@ +'use strict'; + +var Promise = require('bluebird'); +var extend = require('util')._extend; + +module.exports = function(user) { + user.on('attached', function(app) { + app.on('started', function() { + var Role = user.app.models.Role; + Role.registerResolver('$dynamicRole', function(role, ctx, next) { + ctx.remotingContext.args.options = ctx.remotingContext.args.options || {}; + ctx.remotingContext.args.options.canInjectCtxOptionsInCustomRoleResolver = true; + next(); + }); + }); + }); + + user.createOptionsFromRemotingContext = function(ctx) { + return extend(this.base.createOptionsFromRemotingContext(ctx), { + currentUserId: ctx.req.accessToken && ctx.req.accessToken.userId, + }); + }; + + user.beforeRemote('testInjectedOptions', function(ctx, unused, next) { + if (!ctx.args.options.accessToken) return next(); + ctx.args.options.canReadCtxOptionsInBeforeRemote = ctx.args.options.canInjectCtxOptionsInCustomRoleResolver ? true : false; + user.findById(ctx.args.options.accessToken.userId, function(err, user) { + if (err) return next(err); + ctx.args.options.currentUser = user; + next(); + }); + }); + + user.observe('loaded', function(ctx, next) { + ctx.options = ctx.options || {}; + ctx.options.canReadCtxOptionsInObserveLoaded = ctx.options.canInjectCtxOptionsInCustomRoleResolver ? true : false; + ctx.options.canInjectCtxOptionsInObserveLoaded = true; + next(); + }); + + user.remoteMethod('testInjectedOptions', { + http: {verb: 'get', path: '/:id/testInjectedOptions'}, + accepts: [ + {arg: 'id', type: 'string', required: true}, + {arg: 'options', type: 'object', http: 'optionsFromRequest'}, + ], + returns: {arg: 'data', type: 'object', root: true}, + }); + + user.testInjectedOptions = function(id, ctx) { + return Promise.resolve({ + accessToken: ctx.accessToken, + user: ctx.currentUser, + currentUserId: ctx.currentUserId, + canInjectCtxOptionsInCustomRoleResolver: ctx.canInjectCtxOptionsInCustomRoleResolver || false, + canReadCtxOptionsInObserveLoaded: ctx.canReadCtxOptionsInObserveLoaded || false, + canInjectCtxOptionsInObserveLoaded: ctx.canInjectCtxOptionsInObserveLoaded || false, + canReadCtxOptionsInBeforeRemote: ctx.canReadCtxOptionsInBeforeRemote || false, + }); + }; +}; diff --git a/server/models/user.json b/server/models/user.json new file mode 100644 index 0000000..9f25105 --- /dev/null +++ b/server/models/user.json @@ -0,0 +1,37 @@ +{ + "name": "user", + "plural": "users", + "base": "User", + "idInjection": true, + "strict": "true", + "options": { + "validateUpsert": true + }, + "mixins": {}, + "properties": {}, + "hidden": [], + "protected": [], + "validations": [], + "relations": {}, + "acls": [ + { + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$owner", + "permission": "ALLOW", + "property": [ + "testInjectedOptions" + ] + }, + { + "accessType": "EXECUTE", + "principalType": "ROLE", + "principalId": "$dynamicRole", + "permission": "ALLOW", + "property": [ + "testInjectedOptions" + ] + } + ], + "methods": {} +}