ravangen / graphql-rate-limit

🚦 Fixed window rate limiting middleware for GraphQL. Use to limit repeated requests to queries and mutations.
https://www.npmjs.com/package/graphql-rate-limit-directive
MIT License
317 stars 12 forks source link

[QUESTION]: Reset attempts #370

Open simplecommerce opened 1 year ago

simplecommerce commented 1 year ago

Hi,

I was wondering if it was possible to reset the attempts from a mutation.

For example, I have a rate limit on a login mutation. I would like to be able to reset the attempts when a reset password is called. (if applicable).

I am going through the doc to see how I could achieve this but I don't see a clear path yet.

Thanks!

ravangen commented 1 year ago

Hi, thank you for your question!

It is not currently possible, but it seems reasonable. I think it could be achieved via a callback. Currently the limiter only does work before the resolve action, but could also have an optional after action callable (likely only called on success?).

function onResolve(limiter, key, points, result) {
  // Your custom logic based on result
  limiter.reward(key, points);
  return result; // outcome of the original resolve (could transform if needed)
}

const resolvers = {
  Query: {
    quote: {
      resolve: () =>
        'The future is something which everyone reaches at the rate of sixty minutes an hour, whatever he does, whoever he is. ― C.S. Lewis',
      extensions: {
        // IMPORTANT: Specify any overrides via field's extensions under directive's name
        [directiveName]: {
          onResolve: onResolve,
        }
      }
    },
  },
};

Rate limiter wraps resolve, and would return the result of onResolve when provided, otherwise resolve as normal.

I can try to put together something to this effect in the next week.

At some point, you may want your own rate limiter within a resolver instead of a general purpose one.

simplecommerce commented 1 year ago

Hi, thank you for your question!

It is not currently possible, but it seems reasonable. I think it could be achieved via a callback. Currently the limiter only does work before the resolve action, but could also have an optional after action callable (likely only called on success?).

function onResolve(limiter, key, points, result) {
  // Your custom logic based on result
  limiter.reward(key, points);
  return result; // outcome of the original resolve (could transform if needed)
}

const resolvers = {
  Query: {
    quote: {
      resolve: () =>
        'The future is something which everyone reaches at the rate of sixty minutes an hour, whatever he does, whoever he is. ― C.S. Lewis',
      extensions: {
        // IMPORTANT: Specify any overrides via field's extensions under directive's name
        [directiveName]: {
          onResolve: onResolve,
        }
      }
    },
  },
};

Rate limiter wraps resolve, and would return the result of onResolve when provided, otherwise resolve as normal.

I can try to put together something to this effect in the next week.

At some point, you may want your own rate limiter within a resolver instead of a general purpose one.

What do you mean by:

At some point, you may want your own rate limiter within a resolver instead of a general purpose one.

Would you suggest we build our own specific one based on example libraries such as this one?

I do agree that a general one makes it difficult to customize per resolver. I was trying to think of a way of extending this one to do so.

simplecommerce commented 1 year ago

Ah, I also forgot to ask, how would we be able to reset an attempt if such a feature was implemented? For example, if I reached 5 out of 6 times and the last attempt is successful, i'd want to reset the count to 0 for that specific person.

ravangen commented 1 year ago

At some point, you may want your own rate limiter within a resolver instead of a general purpose one.

Would you suggest we build our own specific one based on example libraries such as this one?

This library builds on top of rate-limiter-flexible. You could instantiate your own limiter instance in resolve.

I think a callback is reasonable feature to add, but this library won't necessarily cover 100% of all custom cases..

simplecommerce commented 1 year ago

At some point, you may want your own rate limiter within a resolver instead of a general purpose one.

Would you suggest we build our own specific one based on example libraries such as this one?

This library builds on top of rate-limiter-flexible. You could instantiate your own limiter instance in resolve.

I think a callback is reasonable feature to add, but this library won't necessarily cover 100% of all custom cases..

Thanks I will take a look at the library you mentioned.