RateLimiterMiddlewearTests.coffee 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. SandboxedModule = require('sandboxed-module')
  2. sinon = require('sinon')
  3. require('chai').should()
  4. modulePath = require('path').join __dirname, '../../../../app/js/Features/Security/RateLimiterMiddlewear'
  5. describe "RateLimiterMiddlewear", ->
  6. beforeEach ->
  7. @RateLimiterMiddlewear = SandboxedModule.require modulePath, requires:
  8. '../../infrastructure/RateLimiter' : @RateLimiter = {}
  9. "logger-sharelatex": @logger = {warn: sinon.stub()}
  10. @req =
  11. params: {}
  12. session: {}
  13. @res =
  14. status: sinon.stub()
  15. write: sinon.stub()
  16. end: sinon.stub()
  17. @next = sinon.stub()
  18. describe "rateLimit", ->
  19. beforeEach ->
  20. @rateLimiter = @RateLimiterMiddlewear.rateLimit({
  21. endpointName: "test-endpoint"
  22. params: ["project_id", "doc_id"]
  23. timeInterval: 42
  24. maxRequests: 12
  25. })
  26. @req.params = {
  27. project_id: @project_id = "project-id"
  28. doc_id: @doc_id = "doc-id"
  29. }
  30. describe "when under the rate limit with logged in user", ->
  31. beforeEach ->
  32. @req.session.user = { _id: @user_id = "user-id" }
  33. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
  34. @rateLimiter(@req, @res, @next)
  35. it "should call the rate limiter backend with the user_id", ->
  36. @RateLimiter.addCount
  37. .calledWith({
  38. endpointName: "test-endpoint"
  39. timeInterval: 42
  40. throttle: 12
  41. subjectName: "#{@project_id}:#{@doc_id}:#{@user_id}"
  42. })
  43. .should.equal true
  44. it "should pass on to next()", ->
  45. @next.called.should.equal true
  46. describe "when under the rate limit with anonymous user", ->
  47. beforeEach ->
  48. @req.ip = @ip = "1.2.3.4"
  49. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
  50. @rateLimiter(@req, @res, @next)
  51. it "should call the rate limiter backend with the ip address", ->
  52. @RateLimiter.addCount
  53. .calledWith({
  54. endpointName: "test-endpoint"
  55. timeInterval: 42
  56. throttle: 12
  57. subjectName: "#{@project_id}:#{@doc_id}:#{@ip}"
  58. })
  59. .should.equal true
  60. it "should pass on to next()", ->
  61. @next.called.should.equal true
  62. describe "when over the rate limit", ->
  63. beforeEach ->
  64. @req.session.user = { _id: @user_id = "user-id" }
  65. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, false)
  66. @rateLimiter(@req, @res, @next)
  67. it "should return a 429", ->
  68. @res.status.calledWith(429).should.equal true
  69. @res.end.called.should.equal true
  70. it "should not continue", ->
  71. @next.called.should.equal false
  72. it "should log a warning", ->
  73. @logger.warn
  74. .calledWith({
  75. endpointName: "test-endpoint"
  76. timeInterval: 42
  77. throttle: 12
  78. subjectName: "#{@project_id}:#{@doc_id}:#{@user_id}"
  79. }, "rate limit exceeded")
  80. .should.equal true