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

stashBefore - Invalid query parameter $disableStashBefore #511

Open
RaduGrama opened this issue Mar 8, 2019 · 6 comments
Open

stashBefore - Invalid query parameter $disableStashBefore #511

RaduGrama opened this issue Mar 8, 2019 · 6 comments

Comments

@RaduGrama
Copy link

Steps to reproduce

Add stashBefore() to the hooks of a simple service. The code looks like:

const { stashBefore } = require("feathers-hooks-common");

module.exports = {
  before: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [stashBefore()],
    remove: [stashBefore()]
  },

  after: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  },

  error: {
    all: [],
    find: [],
    get: [],
    create: [],
    update: [],
    patch: [],
    remove: []
  }
};

Expected behavior

No errors.

Actual behavior

error: BadRequest: Invalid query parameter $disableStashBefore
    at new BadRequest (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/node_modules/@feathersjs/errors/lib/index.js:86:17)
    at _.each (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/filter-query.js:48:17)
    at Object.keys.forEach.key (<whatever>/node_modules/@feathersjs/commons/lib/utils.js:12:39)
    at Array.forEach (<anonymous>)
    at Object.each (<whatever>/node_modules/@feathersjs/commons/lib/utils.js:12:24)
    at cleanQuery (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/filter-query.js:41:7)
    at filterQuery (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/filter-query.js:107:18)
    at Object.filterQuery (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/service.js:46:20)
    at Object._find (<whatever>/node_modules/feathers-knex/lib/index.js:156:47)
    at Object._findOrGet (<whatever>/node_modules/feathers-knex/lib/index.js:224:17)
    at Object._get (<whatever>/node_modules/feathers-knex/lib/index.js:228:17)
    at callMethod (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/service.js:9:20)
    at Object.get (<whatever>/node_modules/feathers-knex/node_modules/@feathersjs/adapter-commons/lib/service.js:56:12)
    at processHooks.call.then.hookObject (<whatever>/node_modules/@feathersjs/feathers/lib/hooks/index.js:56:27)
    at <anonymous>

Not sure if this is an issue or misconfiguration.

@eddyystop
Copy link
Collaborator

Its failing in the FeathersJS hook handler either on the get call or after it returns. Please log the id and params before this line https://github.com/feathers-plus/feathers-hooks-common/blob/master/lib/services/stash-before.js#L29 and log that control gets to before https://github.com/feathers-plus/feathers-hooks-common/blob/master/lib/services/stash-before.js#L31 .

@cdelaorden
Copy link

cdelaorden commented May 30, 2019

We also have the same issue and have found a workaround.

The reason is that the stashBefore hook is setting a $disableStashBefore property in the params.query object (for reasons I've yet to understand as it feels like a hack, when you have the full context to share info between hooks). It seems that params.query is also send/recognized by the DB adapter get method, and marked as invalid when using feathers-mongoose, in my case.

The outcome of the error is that context.params.before is undefined because the get call fails, defeating the purpose of using stashBefore at all. :)

To prove my point, the simple solution is to use another hook from this package, discardQuery, and set it up before get to discard that parameter. Add it and the error disappears:

Example config:

before: {     
      get: [discardQuery('$disableStashBefore')],
      patch: [stashBefore(), yourHookThatNeedsStash, ...]
    }

Regarding the reasons of putting $disableStashBefore, if it's there to avoid double stashing, it does seem pretty weird that anyone would be stashing before a get method, because that method is idempotent, nothing can change.

Of course this workaround may have another implications, perhaps @eddyystop you can explain the reasoning or the need of that query parameter to let people know of possible side-effects.

@eddyystop
Copy link
Collaborator

eddyystop commented May 31, 2019 via email

@cdelaorden
Copy link

cdelaorden commented Jun 3, 2019

Any of the populate hooks will cause another service to read records. We don't want those other services to also try to stash records if they too use the stashRecird hook. The $disableStash flag is set by the root service to prevent this. It may look hacky but it's traditional Feathers.

Sure, I'm sorry if it sounded rude on my part, not my intention at all. :)

In that case perhaps the hook should check if something is already in context.params.before or the configured before param to avoid other stashes, instead of setting an incompatible param?

I'm not too familiar with the hooks common code, but the status now is that, at least in some ORM adapters (knex from the original issue, mongoose in my case), using this stashBefore hook throws the error mentioned in this issue's title, preventing the hook from working at all. Do you have any suggestions on the issue itself?

@marshallswain
Copy link
Member

marshallswain commented Aug 3, 2019

I believe the simplest solution to this is to move the $disableStashBefore directive out of the query, and up one level into context.params. This sidesteps the query sanitization process while allowing the rest of the functionality to work as expected.

https://github.com/feathers-plus/feathers-hooks-common/blob/master/lib/services/stash-before.js#L11

So we replace

params.query.$disableStashBefore

with

params.$disableStashBefore

@FossPrime
Copy link
Contributor

FossPrime commented Sep 27, 2019

I'm in agreement with @marshallswain. The proposed API looks like https://feathers-plus.github.io/v1/feathers-hooks-common/#paramsforserver ... and thus is not unusual. It also allows us to use stashBefore only on patch for instance. Which helps performance and readability.

As a temporary fix, we should update the doc and mention that you MUST have stashBefore on the get before hook, the other placements are optional.

Here's how my patch2Update application hook looks because of this issue:

import patch2Update from './hooks/patch2Update.js'
import { discardQuery } from 'feathers-hooks-common'

export default {
  before: {
    get: [ discardQuery('$disableStashBefore') ],
    patch: [ patch2Update() ]
  }
}

Here's how it COULD look with marshall's fix:

import patch2Update from './hooks/patch2Update.js'

export default {
  before: {
    patch: [ patch2Update() ]
  }
}

Are we taking PR's?

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

No branches or pull requests

5 participants