AdminAuthorizationHelperTests.js 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. const { expect } = require('chai')
  2. const SandboxedModule = require('sandboxed-module')
  3. const sinon = require('sinon')
  4. const MockRequest = require('../helpers/MockRequest')
  5. const MockResponse = require('../helpers/MockResponse')
  6. const modulePath =
  7. '../../../../app/src/Features/Helpers/AdminAuthorizationHelper'
  8. describe('AdminAuthorizationHelper', function () {
  9. beforeEach(function () {
  10. this.fireHook = sinon.stub().resolves([])
  11. this.AdminAuthorizationHelper = SandboxedModule.require(modulePath, {
  12. requires: {
  13. '@overleaf/settings': {
  14. adminPrivilegeAvailable: true,
  15. adminUrl: 'https://admin.overleaf.com',
  16. },
  17. '../../infrastructure/Modules': {
  18. promises: {
  19. hooks: {
  20. fire: this.fireHook,
  21. },
  22. },
  23. },
  24. },
  25. })
  26. })
  27. describe('getAdminCapabilities', function () {
  28. describe('when modules return capabilities', function () {
  29. let result
  30. const module1Capabilities = ['capability1', 'capability2']
  31. const module2Capabilities = ['capability2', 'capability3']
  32. beforeEach(async function () {
  33. this.fireHook.resolves([module1Capabilities, module2Capabilities])
  34. result = await this.AdminAuthorizationHelper.getAdminCapabilities({})
  35. })
  36. it('returns true for adminCapabilitiesAvailable', async function () {
  37. expect(result.adminCapabilitiesAvailable).to.be.true
  38. })
  39. it('returns a flattened array of the returned capabilities', function () {
  40. expect(result.adminCapabilities)
  41. .to.be.an('array')
  42. .that.includes(...module1Capabilities, ...module2Capabilities)
  43. })
  44. })
  45. describe('when no module returns capabilities', function () {
  46. let result
  47. beforeEach(async function () {
  48. result = await this.AdminAuthorizationHelper.getAdminCapabilities({})
  49. })
  50. it('returns false for adminCapabilitiesAvailable', function () {
  51. expect(result.adminCapabilitiesAvailable).to.be.false
  52. })
  53. it('returns an empty adminCapabilities array', function () {
  54. expect(result.adminCapabilities).to.be.an('array').that.is.empty
  55. })
  56. })
  57. })
  58. describe('addHasAdminCapabilityToLocals', function () {
  59. describe('when getting capabilities from modules throws an error', function () {
  60. beforeEach(async function () {
  61. this.fireHook.rejects(new Error('Module error'))
  62. this.req = new MockRequest()
  63. this.res = new MockResponse()
  64. this.next = sinon.stub()
  65. this.user = {
  66. isAdmin: false,
  67. }
  68. this.req.logger = {
  69. warn: sinon.stub(),
  70. }
  71. this.req.session = {
  72. user: this.user,
  73. }
  74. await this.AdminAuthorizationHelper.addHasAdminCapabilityToLocals(
  75. this.req,
  76. this.res,
  77. this.next
  78. )
  79. })
  80. it('defines hasAdminCapability on res.locals', function () {
  81. expect(this.res.locals).to.have.property('hasAdminCapability')
  82. })
  83. it('returns false when called with any capability', function () {
  84. expect(this.res.locals.hasAdminCapability('capability1')).to.be.false
  85. })
  86. it('logs a warning', function () {
  87. expect(this.logger.warn).to.have.been.calledOnce
  88. expect(this.logger.warn.firstCall.args[0]).to.have.property('error')
  89. expect(this.logger.warn.firstCall.args[0].error.message).to.equal(
  90. 'Module error'
  91. )
  92. })
  93. })
  94. describe('when admin capabilities are not available', function () {
  95. describe('user is not an admin', function () {
  96. beforeEach(async function () {
  97. this.req = new MockRequest()
  98. this.res = new MockResponse()
  99. this.next = sinon.stub()
  100. this.user = {
  101. isAdmin: false,
  102. }
  103. this.req.session = {
  104. user: this.user,
  105. }
  106. await this.AdminAuthorizationHelper.addHasAdminCapabilityToLocals(
  107. this.req,
  108. this.res,
  109. this.next
  110. )
  111. })
  112. it('defines hasAdminCapability on res.locals', function () {
  113. expect(this.res.locals).to.have.property('hasAdminCapability')
  114. })
  115. it('returns false when called with any capability', function () {
  116. expect(this.res.locals.hasAdminCapability('capability1')).to.be.false
  117. })
  118. })
  119. describe('user is an admin', function () {
  120. beforeEach(async function () {
  121. this.req = new MockRequest()
  122. this.res = new MockResponse()
  123. this.next = sinon.stub()
  124. this.user = {
  125. isAdmin: true,
  126. }
  127. this.req.session = {
  128. user: this.user,
  129. }
  130. await this.AdminAuthorizationHelper.addHasAdminCapabilityToLocals(
  131. this.req,
  132. this.res,
  133. this.next
  134. )
  135. })
  136. it('defines hasAdminCapability on res.locals', function () {
  137. expect(this.res.locals).to.have.property('hasAdminCapability')
  138. })
  139. it('returns true when called with any capability', function () {
  140. expect(this.res.locals.hasAdminCapability('capability1')).to.be.true
  141. })
  142. })
  143. })
  144. describe('when admin capabilities are available', function () {
  145. beforeEach(function () {
  146. this.fireHook.resolves(['capability1', 'capability2'])
  147. })
  148. describe('user is not an admin', function () {
  149. beforeEach(async function () {
  150. this.req = new MockRequest()
  151. this.res = new MockResponse()
  152. this.next = sinon.stub()
  153. this.user = {
  154. isAdmin: false,
  155. }
  156. this.req.session = {
  157. user: this.user,
  158. }
  159. await this.AdminAuthorizationHelper.addHasAdminCapabilityToLocals(
  160. this.req,
  161. this.res,
  162. this.next
  163. )
  164. })
  165. it('defines hasAdminCapability on res.locals', function () {
  166. expect(this.res.locals).to.have.property('hasAdminCapability')
  167. })
  168. it('returns false when called with a capability the user has', function () {
  169. expect(this.res.locals.hasAdminCapability('capability1')).to.be.false
  170. })
  171. it('returns false when called with a capability the user does not have', function () {
  172. expect(this.res.locals.hasAdminCapability('capability3')).to.be.false
  173. })
  174. })
  175. describe('user is an admin', function () {
  176. beforeEach(async function () {
  177. this.req = new MockRequest()
  178. this.res = new MockResponse()
  179. this.next = sinon.stub()
  180. this.user = {
  181. isAdmin: true,
  182. }
  183. this.req.session = {
  184. user: this.user,
  185. }
  186. await this.AdminAuthorizationHelper.addHasAdminCapabilityToLocals(
  187. this.req,
  188. this.res,
  189. this.next
  190. )
  191. })
  192. it('defines hasAdminCapability on res.locals', function () {
  193. expect(this.res.locals).to.have.property('hasAdminCapability')
  194. })
  195. it('returns true when called with a capability the user has', function () {
  196. expect(this.res.locals.hasAdminCapability('capability2')).to.be.true
  197. })
  198. it('returns false when called with a capability the user does not have', function () {
  199. expect(this.res.locals.hasAdminCapability('capability3')).to.be.false
  200. })
  201. })
  202. })
  203. })
  204. })