Set juggler options for remote calls

This commit is contained in:
Raymond Feng 2018-11-12 13:53:00 -08:00
parent a239a11656
commit f1c613ac07
3 changed files with 57 additions and 12 deletions

View File

@ -470,14 +470,14 @@ module.exports = function(registry) {
if (options.accepts) {
options = extend({}, options);
options.accepts = setupOptionsArgs(options.accepts);
options.accepts = setupOptionsArgs(options.accepts, this);
}
this.sharedClass.defineMethod(name, options);
this.emit('remoteMethodAdded', this.sharedClass);
};
function setupOptionsArgs(accepts) {
function setupOptionsArgs(accepts, modelClass) {
if (!Array.isArray(accepts))
accepts = [accepts];
@ -485,21 +485,33 @@ module.exports = function(registry) {
if (arg.http && arg.http === 'optionsFromRequest') {
// clone to preserve the input value
arg = extend({}, arg);
arg.http = createOptionsViaModelMethod;
arg.http = createOptionsViaModelMethod.bind(modelClass);
}
return arg;
});
}
function createOptionsViaModelMethod(ctx) {
var EMPTY_OPTIONS = {};
var ModelCtor = ctx.method && ctx.method.ctor;
if (!ModelCtor)
return EMPTY_OPTIONS;
var ModelCtor = (ctx.method && ctx.method.ctor) || this;
/**
* Configure default values for juggler settings to protect user-supplied
* input from attacking juggler
*/
var DEFAULT_OPTIONS = {
// Default to `true` so that hidden properties cannot be used in query
prohibitHiddenPropertiesInQuery: ModelCtor._getProhibitHiddenPropertiesInQuery({}, true),
// Default to `12` for the max depth of a query object
maxDepthOfQuery: ModelCtor._getMaxDepthOfQuery({}, 12),
// Default to `32` for the max depth of a data object
maxDepthOfData: ModelCtor._getMaxDepthOfData({}, 32),
};
if (typeof ModelCtor.createOptionsFromRemotingContext !== 'function')
return EMPTY_OPTIONS;
return DEFAULT_OPTIONS;
debug('createOptionsFromRemotingContext for %s', ctx.method.stringName);
return ModelCtor.createOptionsFromRemotingContext(ctx);
return Object.assign(DEFAULT_OPTIONS,
ModelCtor.createOptionsFromRemotingContext(ctx));
}
/**

View File

@ -49,7 +49,7 @@
"inflection": "^1.6.0",
"isemail": "^2.2.1",
"loopback-connector-remote": "^3.0.0",
"loopback-datasource-juggler": "^3.18.0",
"loopback-datasource-juggler": "^3.28.0",
"loopback-filters": "^1.0.0",
"loopback-phase": "^3.0.0",
"nodemailer": "^4.0.1",

View File

@ -924,11 +924,15 @@ describe.onServer('Remote Methods', function() {
});
describe('Model.createOptionsFromRemotingContext', function() {
var app, TestModel, accessToken, userId, actualOptions;
var app, TestModel, accessToken, actualOptions;
before(setupAppAndRequest);
before(createUserAndAccessToken);
beforeEach(function() {
TestModel.definition.settings = {};
});
it('sets empty options.accessToken for anonymous requests', function(done) {
request(app).get('/TestModels/saveOptions')
.expect(204, function(err) {
@ -938,6 +942,36 @@ describe.onServer('Remote Methods', function() {
});
});
it('sets options for juggler', function(done) {
request(app).get('/TestModels/saveOptions')
.expect(204, function(err) {
if (err) return done(err);
expect(actualOptions).to.include({
prohibitHiddenPropertiesInQuery: true,
maxDepthOfQuery: 12,
maxDepthOfData: 32,
});
done();
});
});
it('honors model settings to create options for juggler', function(done) {
TestModel.definition.settings = {
prohibitHiddenPropertiesInQuery: false,
maxDepthOfData: 64,
};
request(app).get('/TestModels/saveOptions')
.expect(204, function(err) {
if (err) return done(err);
expect(actualOptions).to.include({
prohibitHiddenPropertiesInQuery: false,
maxDepthOfQuery: 12,
maxDepthOfData: 64,
});
done();
});
});
it('sets options.accessToken for authorized requests', function(done) {
request(app).get('/TestModels/saveOptions')
.set('Authorization', accessToken.id)
@ -1028,7 +1062,6 @@ describe.onServer('Remote Methods', function() {
return User.login(CREDENTIALS);
}).then(function(token) {
accessToken = token;
userId = token.userId;
});
}
});