RemoveDeletedUsersFromTokenAccessRefsTests.js 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  1. const { db, ObjectId } = require('../../../app/src/infrastructure/mongodb')
  2. const { promisify } = require('util')
  3. const { exec } = require('child_process')
  4. const logger = require('@overleaf/logger/logging-manager')
  5. const { expect } = require('chai')
  6. describe('RemoveDeletedUsersFromTokenAccessRefsTests', function () {
  7. const userId1 = new ObjectId()
  8. const userId2 = new ObjectId()
  9. const userId3 = new ObjectId()
  10. let insertedUsersCount
  11. beforeEach('insert users', async function () {
  12. const users = await db.users.insertMany([
  13. { _id: userId1, email: 'user1@example.com' },
  14. ])
  15. insertedUsersCount = users.insertedCount
  16. })
  17. const projectId1 = new ObjectId('65d726e807c024c8db43be22')
  18. const projectId2 = new ObjectId('65d726e807c024c8db43be23')
  19. const projectId3 = new ObjectId('65d726e807c024c8db43be24')
  20. const projectId4 = new ObjectId('65d726e807c024c8db43be25')
  21. let insertedProjects
  22. beforeEach('insert projects', async function () {
  23. insertedProjects = await db.projects.insertMany([
  24. {
  25. _id: projectId1,
  26. tokenAccessReadAndWrite_refs: [userId1],
  27. tokenAccessReadOnly_refs: [],
  28. },
  29. {
  30. _id: projectId2,
  31. tokenAccessReadAndWrite_refs: [userId2],
  32. tokenAccessReadOnly_refs: [],
  33. },
  34. {
  35. _id: projectId3,
  36. tokenAccessReadAndWrite_refs: [userId3],
  37. },
  38. {
  39. _id: projectId4,
  40. },
  41. ])
  42. })
  43. let stdOut
  44. const runScript = async (dryRun, projectsList) => {
  45. let result
  46. try {
  47. result = await promisify(exec)(
  48. [
  49. 'VERBOSE_LOGGING=true',
  50. 'node',
  51. 'scripts/remove_deleted_users_from_token_access_refs',
  52. dryRun,
  53. projectsList,
  54. ].join(' ')
  55. )
  56. } catch (error) {
  57. // dump details like exit code, stdErr and stdOut
  58. logger.error({ error }, 'script failed')
  59. throw error
  60. }
  61. const { stdout } = result
  62. stdOut = stdout
  63. expect(stdOut).to.match(new RegExp(`User ids count: ${insertedUsersCount}`))
  64. }
  65. describe('dry-run=true', function () {
  66. beforeEach('run script', async function () {
  67. await runScript('--dry-run=true')
  68. expect(stdOut).to.match(/doing dry run/i)
  69. })
  70. it('should show current user id to be removed', function () {
  71. expect(stdOut).to.match(
  72. new RegExp(
  73. `Found deleted user id: ${userId2.toString()} in project: ${projectId2.toString()}`
  74. )
  75. )
  76. expect(stdOut).to.match(
  77. new RegExp(
  78. `DRY RUN - would remove deleted ${userId2.toString()} from all projects \\(found in project ${projectId2.toString()}\\)`
  79. )
  80. )
  81. expect(stdOut).to.match(
  82. new RegExp(
  83. `Found deleted user id: ${userId3.toString()} in project: ${projectId3.toString()}`
  84. )
  85. )
  86. expect(stdOut).to.match(
  87. new RegExp(
  88. `DRY RUN - would remove deleted ${userId3.toString()} from all projects \\(found in project ${projectId3.toString()}\\)`
  89. )
  90. )
  91. })
  92. it('should show projects with non-existing token access fields', function () {
  93. expect(stdOut)
  94. .to.match(
  95. new RegExp(
  96. `DRY RUN - would fix non-existing token access fields in project ${projectId3.toString()}`
  97. )
  98. )
  99. .and.match(
  100. new RegExp(
  101. `DRY RUN - would fix non-existing token access fields in project ${projectId4.toString()}`
  102. )
  103. )
  104. })
  105. it('should show the user ids (and their count) to be deleted', function () {
  106. expect(stdOut).to.match(
  107. new RegExp(
  108. `DRY RUN - would delete user ids \\(2\\)\\n${userId2.toString()}\\n${userId3.toString()}`
  109. )
  110. )
  111. })
  112. it('should show the project ids (and their count) that needs fixing', function () {
  113. expect(stdOut).to.match(
  114. new RegExp(
  115. `Projects with deleted user ids \\(2\\)\\n${projectId2.toString()}\\n${projectId3.toString()}`
  116. )
  117. )
  118. })
  119. it('should not fix the token access fields of projects', async function () {
  120. const projects = await db.projects
  121. .find({}, { $sort: { _id: 1 } })
  122. .toArray()
  123. expect(projects).to.deep.equal([
  124. {
  125. _id: projectId1,
  126. tokenAccessReadAndWrite_refs: [userId1],
  127. tokenAccessReadOnly_refs: [],
  128. },
  129. {
  130. _id: projectId2,
  131. tokenAccessReadAndWrite_refs: [userId2],
  132. tokenAccessReadOnly_refs: [],
  133. },
  134. {
  135. _id: projectId3,
  136. tokenAccessReadAndWrite_refs: [userId3],
  137. },
  138. {
  139. _id: projectId4,
  140. },
  141. ])
  142. })
  143. })
  144. describe('dry-run=false', function () {
  145. beforeEach('run script', async function () {
  146. await runScript('--dry-run=false')
  147. expect(stdOut).to.not.match(/dry run/i)
  148. })
  149. it('should show current user id to be removed', function () {
  150. expect(stdOut).to.match(
  151. new RegExp(
  152. `Found deleted user id: ${userId2.toString()} in project: ${projectId2.toString()}`
  153. )
  154. )
  155. expect(stdOut).to.match(
  156. new RegExp(
  157. `Removing deleted ${userId2.toString()} from all projects \\(found in project ${projectId2.toString()}\\)`
  158. )
  159. )
  160. expect(stdOut).to.match(
  161. new RegExp(
  162. `Found deleted user id: ${userId3.toString()} in project: ${projectId3.toString()}`
  163. )
  164. )
  165. expect(stdOut).to.match(
  166. new RegExp(
  167. `Removing deleted ${userId3.toString()} from all projects \\(found in project ${projectId3.toString()}\\)`
  168. )
  169. )
  170. })
  171. it('should show fixed projects with non-existing token access fields', function () {
  172. expect(stdOut)
  173. .to.match(
  174. new RegExp(
  175. `Fixed non-existing token access fields in project ${projectId3.toString()}`
  176. )
  177. )
  178. .and.match(
  179. new RegExp(
  180. `Fixed non-existing token access fields in project ${projectId4.toString()}`
  181. )
  182. )
  183. })
  184. it('should show the deleted user ids (and their count) that were removed', function () {
  185. expect(stdOut).to.match(
  186. new RegExp(
  187. `Deleted user ids \\(2\\)\\n${userId2.toString()}\\n${userId3.toString()}`
  188. )
  189. )
  190. })
  191. it('should show the project ids (and their count) that were fixed', function () {
  192. expect(stdOut).to.match(
  193. new RegExp(
  194. `Projects with deleted user ids \\(2\\)\\n${projectId2.toString()}\\n${projectId3.toString()}`
  195. )
  196. )
  197. })
  198. it('should fix the token access fields of projects', async function () {
  199. const [, ...fixedProjects] = await db.projects
  200. .find({}, { $sort: { _id: 1 } })
  201. .toArray()
  202. expect(fixedProjects).to.deep.equal([
  203. {
  204. _id: projectId2,
  205. tokenAccessReadAndWrite_refs: [],
  206. tokenAccessReadOnly_refs: [],
  207. },
  208. {
  209. _id: projectId3,
  210. tokenAccessReadAndWrite_refs: [],
  211. tokenAccessReadOnly_refs: [],
  212. },
  213. {
  214. _id: projectId4,
  215. tokenAccessReadOnly_refs: [],
  216. tokenAccessReadAndWrite_refs: [],
  217. },
  218. ])
  219. })
  220. })
  221. describe('projects=projectId2', function () {
  222. beforeEach('run script', async function () {
  223. const projectId2 = insertedProjects.insertedIds[1]
  224. await runScript('--dry-run=false', `--projects=${projectId2.toString()}`)
  225. })
  226. it('should fix only the projects provided', async function () {
  227. const [project1, project2, project3] = await db.projects
  228. .find({}, { $sort: { _id: 1 } })
  229. .toArray()
  230. expect(project1.tokenAccessReadAndWrite_refs.length).to.be.gt(0)
  231. expect(project2.tokenAccessReadAndWrite_refs.length).to.eq(0) // deleted user removed
  232. expect(project3.tokenAccessReadAndWrite_refs.length).to.be.gt(0)
  233. })
  234. })
  235. })