RateLimiterMiddlewearTests.coffee 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  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. @res =
  13. status: sinon.stub()
  14. write: sinon.stub()
  15. end: sinon.stub()
  16. @next = sinon.stub()
  17. describe "rateLimit", ->
  18. beforeEach ->
  19. @rateLimiter = @RateLimiterMiddlewear.rateLimit({
  20. endpointName: "test-endpoint"
  21. params: ["project_id", "doc_id"]
  22. timeInterval: 42
  23. maxRequests: 12
  24. })
  25. @req.params = {
  26. project_id: @project_id = "project-id"
  27. doc_id: @doc_id = "doc-id"
  28. }
  29. describe "when there is no session", ->
  30. beforeEach ->
  31. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
  32. @req.ip = @ip = "1.2.3.4"
  33. @rateLimiter(@req, @res, @next)
  34. it "should call the rate limiter backend with the ip address", ->
  35. @RateLimiter.addCount
  36. .calledWith({
  37. endpointName: "test-endpoint"
  38. timeInterval: 42
  39. throttle: 12
  40. subjectName: "#{@project_id}:#{@doc_id}:#{@ip}"
  41. })
  42. .should.equal true
  43. it "should pass on to next()", ->
  44. describe "when under the rate limit with logged in user", ->
  45. beforeEach ->
  46. @req.session =
  47. user :
  48. _id: @user_id = "user-id"
  49. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
  50. @rateLimiter(@req, @res, @next)
  51. it "should call the rate limiter backend with the user_id", ->
  52. @RateLimiter.addCount
  53. .calledWith({
  54. endpointName: "test-endpoint"
  55. timeInterval: 42
  56. throttle: 12
  57. subjectName: "#{@project_id}:#{@doc_id}:#{@user_id}"
  58. })
  59. .should.equal true
  60. it "should pass on to next()", ->
  61. @next.called.should.equal true
  62. describe "when under the rate limit with anonymous user", ->
  63. beforeEach ->
  64. @req.ip = @ip = "1.2.3.4"
  65. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, true)
  66. @rateLimiter(@req, @res, @next)
  67. it "should call the rate limiter backend with the ip address", ->
  68. @RateLimiter.addCount
  69. .calledWith({
  70. endpointName: "test-endpoint"
  71. timeInterval: 42
  72. throttle: 12
  73. subjectName: "#{@project_id}:#{@doc_id}:#{@ip}"
  74. })
  75. .should.equal true
  76. it "should pass on to next()", ->
  77. @next.called.should.equal true
  78. describe "when over the rate limit", ->
  79. beforeEach ->
  80. @req.session =
  81. user :
  82. _id: @user_id = "user-id"
  83. @RateLimiter.addCount = sinon.stub().callsArgWith(1, null, false)
  84. @rateLimiter(@req, @res, @next)
  85. it "should return a 429", ->
  86. @res.status.calledWith(429).should.equal true
  87. @res.end.called.should.equal true
  88. it "should not continue", ->
  89. @next.called.should.equal false
  90. it "should log a warning", ->
  91. @logger.warn
  92. .calledWith({
  93. endpointName: "test-endpoint"
  94. timeInterval: 42
  95. throttle: 12
  96. subjectName: "#{@project_id}:#{@doc_id}:#{@user_id}"
  97. }, "rate limit exceeded")
  98. .should.equal true