ProjectOwnershipTransferTests.mjs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. import { expect } from 'chai'
  2. import UserHelper from './helpers/User.mjs'
  3. import Features from '../../../app/src/infrastructure/Features.mjs'
  4. const User = UserHelper.promises
  5. describe('Project ownership transfer', function () {
  6. beforeEach(async function () {
  7. this.ownerSession = new User()
  8. this.collaboratorSession = new User()
  9. this.strangerSession = new User()
  10. this.adminSession = new User()
  11. this.invitedAdminSession = new User()
  12. await this.invitedAdminSession.ensureUserExists()
  13. await this.invitedAdminSession.ensureAdmin()
  14. await this.invitedAdminSession.login()
  15. await this.adminSession.ensureUserExists()
  16. await this.adminSession.ensureAdmin()
  17. await this.ownerSession.login()
  18. await this.collaboratorSession.login()
  19. await this.strangerSession.login()
  20. await this.adminSession.login()
  21. this.owner = await this.ownerSession.get()
  22. this.collaborator = await this.collaboratorSession.get()
  23. this.stranger = await this.strangerSession.get()
  24. this.admin = await this.adminSession.get()
  25. this.invitedAdmin = await this.invitedAdminSession.get()
  26. this.projectId = await this.ownerSession.createProject('Test project')
  27. await this.ownerSession.addUserToProject(
  28. this.projectId,
  29. this.invitedAdmin,
  30. 'readAndWrite'
  31. )
  32. await this.ownerSession.addUserToProject(
  33. this.projectId,
  34. this.collaborator,
  35. 'readAndWrite'
  36. )
  37. })
  38. describe('happy path', function () {
  39. beforeEach(async function () {
  40. await this.ownerSession.transferProjectOwnership(
  41. this.projectId,
  42. this.collaborator._id
  43. )
  44. })
  45. it('changes the project owner', async function () {
  46. const project = await this.collaboratorSession.getProject(this.projectId)
  47. expect(project.owner_ref.toString()).to.equal(
  48. this.collaborator._id.toString()
  49. )
  50. })
  51. it('adds the previous owner as a read/write collaborator', async function () {
  52. // Skip this test in SaaS environments as limited collaborators are enforced
  53. if (Features.hasFeature('saas')) {
  54. this.skip()
  55. }
  56. const project = await this.collaboratorSession.getProject(this.projectId)
  57. expect(project.collaberator_refs.map(x => x.toString())).to.have.members([
  58. this.owner._id.toString(),
  59. this.invitedAdmin._id.toString(),
  60. ])
  61. expect(project.owner_ref.toString()).to.equal(
  62. this.collaborator._id.toString()
  63. )
  64. expect(project.readOnly_refs.map(x => x.toString())).to.be.empty
  65. })
  66. it('adds the previous owner as a read only', async function () {
  67. // Skip this test in non-SaaS environments as unlimited collaborators are allowed
  68. if (!Features.hasFeature('saas')) {
  69. this.skip()
  70. }
  71. const project = await this.collaboratorSession.getProject(this.projectId)
  72. expect(project.collaberator_refs.map(x => x.toString())).to.have.members([
  73. this.invitedAdmin._id.toString(),
  74. ])
  75. expect(project.owner_ref.toString()).to.equal(
  76. this.collaborator._id.toString()
  77. )
  78. expect(project.readOnly_refs.map(x => x.toString())).to.have.members([
  79. this.owner._id.toString(),
  80. ])
  81. })
  82. it('lets the new owner open the project', async function () {
  83. await this.collaboratorSession.openProject(this.projectId)
  84. })
  85. it('lets the previous owner open the project', async function () {
  86. await this.ownerSession.openProject(this.projectId)
  87. })
  88. })
  89. describe('ownership change as admin', function () {
  90. it('lets the invited admin transfer ownership', async function () {
  91. await this.invitedAdminSession.transferProjectOwnership(
  92. this.projectId,
  93. this.collaborator._id
  94. )
  95. const project = await this.invitedAdminSession.getProject(this.projectId)
  96. expect(project.owner_ref.toString()).to.equal(
  97. this.collaborator._id.toString()
  98. )
  99. })
  100. it('lets the non-invited admin transfer ownership', async function () {
  101. await this.adminSession.transferProjectOwnership(
  102. this.projectId,
  103. this.collaborator._id
  104. )
  105. const project = await this.adminSession.getProject(this.projectId)
  106. expect(project.owner_ref.toString()).to.equal(
  107. this.collaborator._id.toString()
  108. )
  109. })
  110. })
  111. describe('validation', function () {
  112. it('lets only the project owner transfer ownership', async function () {
  113. await expect(
  114. this.collaboratorSession.transferProjectOwnership(
  115. this.projectId,
  116. this.collaborator._id
  117. )
  118. ).to.be.rejectedWith(/failed: status=403 /)
  119. })
  120. it('prevents transfers to a non-collaborator', async function () {
  121. await expect(
  122. this.ownerSession.transferProjectOwnership(
  123. this.projectId,
  124. this.stranger._id
  125. )
  126. ).to.be.rejectedWith(/failed: status=403 /)
  127. })
  128. it('allows an admin to transfer to any project to a non-collaborator', async function () {
  129. await expect(
  130. this.adminSession.transferProjectOwnership(
  131. this.projectId,
  132. this.stranger._id
  133. )
  134. ).to.be.fulfilled
  135. })
  136. })
  137. })