Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inject remote context createChangeStream method #3064

Conversation

BramKleinhout
Copy link

@BramKleinhout BramKleinhout commented Jan 3, 2017

Description

Implement, in addition to #3023, the injection of remote context to the options argument of the createChangeStream method.

Related issues

Checklist

  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide

@slnode
Copy link

slnode commented Jan 3, 2017

Can one of the admins verify this patch? To accept patch and trigger a build add comment ".ok\W+to\W+test."

@slnode
Copy link

slnode commented Jan 3, 2017

Can one of the admins verify this patch?

3 similar comments
@slnode
Copy link

slnode commented Jan 3, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Jan 3, 2017

Can one of the admins verify this patch?

@slnode
Copy link

slnode commented Jan 3, 2017

Can one of the admins verify this patch?

@davidcheung
Copy link
Contributor

@BramKleinhout thanks for the contribution!
would you be able to add a test to prevent later regressions?

@BramKleinhout
Copy link
Author

@davidcheung That is no problem, I have added the test for the injection.

@bajtos bajtos self-assigned this Jan 4, 2017
type: 'ReadableStream',
json: true,
},
accepts: {arg: 'options', type: 'object', http: 'optionsFromRequest'},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I did not realise that createChangeStream was already exposing the options argument. The change proposed in this pull request can break existing applications, because right now it's possible to specify options via query string:

GET /api/mymodels/change-stream?options[flag]=value
-> options = {flag: 'value'}

We need to preserve backwards compatibility. The solution is to add a feature flag (a model-level setting) that will control whether the options argument should be provided by the user (current state) or constructed via optionsFromRequest (the new version).

Here is a quick mock-up:

var streamOptionsArg = {arg: 'options', type: 'object'};
// TODO: remove this flag in 4.0
if (PersistedModel.settings.injectChangeStreamOptions) {
  streamOptionsArg.http = 'optionsFromRequest';
}

setRemoting(PersistedModel, 'createChangeStream', {
  // ...,
  accepts: streamOptionsArg,
  returns: // ...
});

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, on the second thought, considering that Operation hooks observers now expect that ctx.options is always constructed by the server and cannot be injected by the client, I think the original options configuration would create a serious security vulnerability and therefore we should change it even though it may break existing apps.

Modify the remoting metadata for the "options" argument to use the new
`http: 'optionsFromRequest'` mapping.

The old configuration, where the clients could set arbitrary "options",
opened a security vulnerability because with "optionsFromReqest" in
place in other PersistedModel methods, users are expecting that
"ctx.options" provided by Operation hooks is always created server-side
and cannot be tampered by clients.
@bajtos bajtos force-pushed the feature-context-for-change-stream branch from 8c8fa75 to 5b6ceff Compare January 13, 2017 14:59
@bajtos
Copy link
Member

bajtos commented Jan 13, 2017

Hmm, it turns out the built-in createChangeStream method does not use the options argument at all, and there are no operation hooks invoked where this options argument could be read.

In that light, it does not make sense to me to modify the way how the options object is initialised.

If you are overriding createChangeStream in your application, I am advising you to hide the built-in method and expose your custom one under a different name (but the same URL).

MyModel.disableRemoteMethodByName('createChangeStream');
MyModel.myCreateChangeStream = function(options, cb) {
  // your custom implementation, possibly calling out to MyModelcreateChangeStream
}

MyModel.remoteMethod('myCreateChangeStream', {
      description: 'Create a change stream.',
      accessType: 'READ',
      http: [
        {verb: 'post', path: '/change-stream'},
        {verb: 'get', path: '/change-stream'},
      ],
      accepts: {arg: 'options', type: 'object', http: 'optionsFromRequest'},
      returns: {arg: 'changes', type: 'ReadableStream', json: true},
});

@bajtos bajtos closed this Jan 13, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants