ClsiCookieManagerTests.js 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. const sinon = require('sinon')
  2. const { assert, expect } = require('chai')
  3. const modulePath = '../../../../app/src/Features/Compile/ClsiCookieManager.js'
  4. const SandboxedModule = require('sandboxed-module')
  5. const realRequst = require('request')
  6. describe('ClsiCookieManager', function () {
  7. beforeEach(function () {
  8. this.redis = {
  9. auth() {},
  10. get: sinon.stub(),
  11. setex: sinon.stub().callsArg(3),
  12. }
  13. this.project_id = '123423431321-proj-id'
  14. this.user_id = 'abc-user-id'
  15. this.request = {
  16. post: sinon.stub(),
  17. cookie: realRequst.cookie,
  18. jar: realRequst.jar,
  19. defaults: () => {
  20. return this.request
  21. },
  22. }
  23. this.settings = {
  24. redis: {
  25. web: 'redis.something',
  26. },
  27. apis: {
  28. clsi: {
  29. url: 'http://clsi.example.com',
  30. },
  31. },
  32. clsiCookie: {
  33. ttlInSeconds: Math.random().toString(),
  34. ttlInSecondsRegular: Math.random().toString(),
  35. key: 'coooookie',
  36. },
  37. }
  38. this.requires = {
  39. '../../infrastructure/RedisWrapper': (this.RedisWrapper = {
  40. client: () => this.redis,
  41. }),
  42. '@overleaf/settings': this.settings,
  43. request: this.request,
  44. }
  45. this.ClsiCookieManager = SandboxedModule.require(modulePath, {
  46. requires: this.requires,
  47. })()
  48. })
  49. describe('getServerId', function () {
  50. it('should call get for the key', function (done) {
  51. this.redis.get.callsArgWith(1, null, 'clsi-7')
  52. this.ClsiCookieManager._getServerId(
  53. this.project_id,
  54. this.user_id,
  55. '',
  56. 'e2',
  57. (err, serverId) => {
  58. if (err) {
  59. return done(err)
  60. }
  61. this.redis.get
  62. .calledWith(`clsiserver:${this.project_id}:${this.user_id}`)
  63. .should.equal(true)
  64. serverId.should.equal('clsi-7')
  65. done()
  66. }
  67. )
  68. })
  69. it('should _populateServerIdViaRequest if no key is found', function (done) {
  70. this.ClsiCookieManager._populateServerIdViaRequest = sinon
  71. .stub()
  72. .yields(null)
  73. this.redis.get.callsArgWith(1, null)
  74. this.ClsiCookieManager._getServerId(
  75. this.project_id,
  76. this.user_id,
  77. '',
  78. (err, serverId) => {
  79. if (err) {
  80. return done(err)
  81. }
  82. this.ClsiCookieManager._populateServerIdViaRequest
  83. .calledWith(this.project_id, this.user_id)
  84. .should.equal(true)
  85. done()
  86. }
  87. )
  88. })
  89. it('should _populateServerIdViaRequest if no key is blank', function (done) {
  90. this.ClsiCookieManager._populateServerIdViaRequest = sinon
  91. .stub()
  92. .yields(null)
  93. this.redis.get.callsArgWith(1, null, '')
  94. this.ClsiCookieManager._getServerId(
  95. this.project_id,
  96. this.user_id,
  97. '',
  98. 'e2',
  99. (err, serverId) => {
  100. if (err) {
  101. return done(err)
  102. }
  103. this.ClsiCookieManager._populateServerIdViaRequest
  104. .calledWith(this.project_id, this.user_id)
  105. .should.equal(true)
  106. done()
  107. }
  108. )
  109. })
  110. })
  111. describe('_populateServerIdViaRequest', function () {
  112. beforeEach(function () {
  113. this.response = 'some data'
  114. this.request.post.callsArgWith(1, null, this.response)
  115. this.ClsiCookieManager.setServerId = sinon.stub().yields(null, 'clsi-9')
  116. })
  117. it('should make a request to the clsi', function (done) {
  118. this.ClsiCookieManager._populateServerIdViaRequest(
  119. this.project_id,
  120. this.user_id,
  121. 'standard',
  122. 'e2',
  123. (err, serverId) => {
  124. if (err) {
  125. return done(err)
  126. }
  127. const args = this.ClsiCookieManager.setServerId.args[0]
  128. args[0].should.equal(this.project_id)
  129. args[1].should.equal(this.user_id)
  130. args[2].should.equal('standard')
  131. args[3].should.equal('e2')
  132. args[4].should.deep.equal(this.response)
  133. done()
  134. }
  135. )
  136. })
  137. it('should return the server id', function (done) {
  138. this.ClsiCookieManager._populateServerIdViaRequest(
  139. this.project_id,
  140. this.user_id,
  141. '',
  142. 'e2',
  143. (err, serverId) => {
  144. if (err) {
  145. return done(err)
  146. }
  147. serverId.should.equal('clsi-9')
  148. done()
  149. }
  150. )
  151. })
  152. })
  153. describe('setServerId', function () {
  154. beforeEach(function () {
  155. this.response = 'dsadsakj'
  156. this.ClsiCookieManager._parseServerIdFromResponse = sinon
  157. .stub()
  158. .returns('clsi-8')
  159. })
  160. it('should set the server id with a ttl', function (done) {
  161. this.ClsiCookieManager.setServerId(
  162. this.project_id,
  163. this.user_id,
  164. 'standard',
  165. 'e2',
  166. this.response,
  167. null,
  168. err => {
  169. if (err) {
  170. return done(err)
  171. }
  172. this.redis.setex
  173. .calledWith(
  174. `clsiserver:${this.project_id}:${this.user_id}`,
  175. this.settings.clsiCookie.ttlInSeconds,
  176. 'clsi-8'
  177. )
  178. .should.equal(true)
  179. done()
  180. }
  181. )
  182. })
  183. it('should set the server id with the regular ttl for reg instance', function (done) {
  184. this.ClsiCookieManager._parseServerIdFromResponse = sinon
  185. .stub()
  186. .returns('clsi-reg-8')
  187. this.ClsiCookieManager.setServerId(
  188. this.project_id,
  189. this.user_id,
  190. 'standard',
  191. 'e2',
  192. this.response,
  193. null,
  194. err => {
  195. if (err) {
  196. return done(err)
  197. }
  198. expect(this.redis.setex).to.have.been.calledWith(
  199. `clsiserver:${this.project_id}:${this.user_id}`,
  200. this.settings.clsiCookie.ttlInSecondsRegular,
  201. 'clsi-reg-8'
  202. )
  203. done()
  204. }
  205. )
  206. })
  207. it('should return the server id', function (done) {
  208. this.ClsiCookieManager.setServerId(
  209. this.project_id,
  210. this.user_id,
  211. 'standard',
  212. 'e2',
  213. this.response,
  214. null,
  215. (err, serverId) => {
  216. if (err) {
  217. return done(err)
  218. }
  219. serverId.should.equal('clsi-8')
  220. done()
  221. }
  222. )
  223. })
  224. it('should not set the server id if clsiCookies are not enabled', function (done) {
  225. delete this.settings.clsiCookie.key
  226. this.ClsiCookieManager = SandboxedModule.require(modulePath, {
  227. globals: {
  228. console,
  229. },
  230. requires: this.requires,
  231. })()
  232. this.ClsiCookieManager.setServerId(
  233. this.project_id,
  234. this.user_id,
  235. 'standard',
  236. 'e2',
  237. this.response,
  238. null,
  239. (err, serverId) => {
  240. if (err) {
  241. return done(err)
  242. }
  243. this.redis.setex.called.should.equal(false)
  244. done()
  245. }
  246. )
  247. })
  248. it('should not set the server id there is no server id in the response', function (done) {
  249. this.ClsiCookieManager._parseServerIdFromResponse = sinon
  250. .stub()
  251. .returns(null)
  252. this.ClsiCookieManager.setServerId(
  253. this.project_id,
  254. this.user_id,
  255. 'standard',
  256. 'e2',
  257. this.response,
  258. null,
  259. (err, serverId) => {
  260. if (err) {
  261. return done(err)
  262. }
  263. this.redis.setex.called.should.equal(false)
  264. done()
  265. }
  266. )
  267. })
  268. it('should also set in the secondary if secondary redis is enabled', function (done) {
  269. this.redis_secondary = { setex: sinon.stub().callsArg(3) }
  270. this.settings.redis.clsi_cookie_secondary = {}
  271. this.RedisWrapper.client = sinon.stub()
  272. this.RedisWrapper.client.withArgs('clsi_cookie').returns(this.redis)
  273. this.RedisWrapper.client
  274. .withArgs('clsi_cookie_secondary')
  275. .returns(this.redis_secondary)
  276. this.ClsiCookieManager = SandboxedModule.require(modulePath, {
  277. globals: {
  278. console,
  279. },
  280. requires: this.requires,
  281. })()
  282. this.ClsiCookieManager._parseServerIdFromResponse = sinon
  283. .stub()
  284. .returns('clsi-8')
  285. this.ClsiCookieManager.setServerId(
  286. this.project_id,
  287. this.user_id,
  288. 'standard',
  289. 'e2',
  290. this.response,
  291. null,
  292. (err, serverId) => {
  293. if (err) {
  294. return done(err)
  295. }
  296. this.redis_secondary.setex
  297. .calledWith(
  298. `clsiserver:${this.project_id}:${this.user_id}`,
  299. this.settings.clsiCookie.ttlInSeconds,
  300. 'clsi-8'
  301. )
  302. .should.equal(true)
  303. done()
  304. }
  305. )
  306. })
  307. })
  308. describe('getCookieJar', function () {
  309. beforeEach(function () {
  310. this.ClsiCookieManager._getServerId = sinon.stub().yields(null, 'clsi-11')
  311. })
  312. it('should return a jar with the cookie set populated from redis', function (done) {
  313. this.ClsiCookieManager.getCookieJar(
  314. this.project_id,
  315. this.user_id,
  316. '',
  317. 'e2',
  318. (err, jar) => {
  319. if (err) {
  320. return done(err)
  321. }
  322. jar._jar.store.idx['clsi.example.com']['/'][
  323. this.settings.clsiCookie.key
  324. ].key.should.equal
  325. jar._jar.store.idx['clsi.example.com']['/'][
  326. this.settings.clsiCookie.key
  327. ].value.should.equal('clsi-11')
  328. done()
  329. }
  330. )
  331. })
  332. it('should return empty cookie jar if clsiCookies are not enabled', function (done) {
  333. delete this.settings.clsiCookie.key
  334. this.ClsiCookieManager = SandboxedModule.require(modulePath, {
  335. globals: {
  336. console,
  337. },
  338. requires: this.requires,
  339. })()
  340. this.ClsiCookieManager.getCookieJar(
  341. this.project_id,
  342. this.user_id,
  343. '',
  344. 'e2',
  345. (err, jar) => {
  346. if (err) {
  347. return done(err)
  348. }
  349. assert.deepEqual(jar, realRequst.jar())
  350. done()
  351. }
  352. )
  353. })
  354. })
  355. })