ProjectAuditLogHandler.test.mjs 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. import { vi, expect } from 'vitest'
  2. import mongodb from 'mongodb-legacy'
  3. import sinon from 'sinon'
  4. const modulePath =
  5. '../../../../app/src/Features/Project/ProjectAuditLogHandler.mjs'
  6. const { ObjectId } = mongodb
  7. const projectId = new ObjectId()
  8. const userId = new ObjectId()
  9. const subscriptionId = new ObjectId()
  10. const previousOwnerId = new ObjectId()
  11. const newOwnerId = new ObjectId()
  12. const subscriptionId2 = new ObjectId()
  13. describe('ProjectAuditLogHandler', function (ctx) {
  14. beforeEach(async function (ctx) {
  15. ctx.createEntryMock = sinon.stub().resolves()
  16. vi.doMock('../../../../app/src/models/ProjectAuditLogEntry', () => ({
  17. ProjectAuditLogEntry: {
  18. create: ctx.createEntryMock,
  19. },
  20. }))
  21. ctx.getUniqueManagedSubscriptionMemberOfMock = sinon.stub().resolves()
  22. vi.doMock(
  23. '../../../../app/src/Features/Subscription/SubscriptionLocator.mjs',
  24. () => ({
  25. default: {
  26. promises: {
  27. getUniqueManagedSubscriptionMemberOf:
  28. ctx.getUniqueManagedSubscriptionMemberOfMock,
  29. },
  30. },
  31. })
  32. )
  33. ctx.ProjectAuditLogHandler = (await import(modulePath)).default
  34. })
  35. describe('addEntry', function () {
  36. it('creates an entry in the database', async function (ctx) {
  37. await ctx.ProjectAuditLogHandler.promises.addEntry(
  38. projectId,
  39. 'project-op',
  40. userId,
  41. '0:0:0:0'
  42. )
  43. expect(ctx.createEntryMock).to.have.been.calledOnceWith({
  44. operation: 'project-op',
  45. projectId,
  46. initiatorId: userId,
  47. ipAddress: '0:0:0:0',
  48. info: {},
  49. })
  50. })
  51. it('does not include managedSubscriptionId when the user is not managed ', async function (ctx) {
  52. await ctx.ProjectAuditLogHandler.promises.addEntry(
  53. projectId,
  54. 'accept-invite', // this event logs managedSubscriptionId when available
  55. userId,
  56. '0:0:0:0'
  57. )
  58. expect(ctx.createEntryMock).not.to.have.been.calledWithMatch({
  59. managedSubscriptionId: subscriptionId,
  60. })
  61. })
  62. it('includes managedSubscriptionId when the user is managed ', async function (ctx) {
  63. ctx.getUniqueManagedSubscriptionMemberOfMock.resolves({
  64. _id: subscriptionId,
  65. })
  66. await ctx.ProjectAuditLogHandler.promises.addEntry(
  67. projectId,
  68. 'accept-invite', // this event logs managedSubscriptionId when available
  69. userId,
  70. '0:0:0:0'
  71. )
  72. expect(ctx.createEntryMock).to.have.been.calledWithMatch({
  73. managedSubscriptionId: subscriptionId.toString(),
  74. })
  75. })
  76. it('does not include managedSubscriptionId when the user is managed, but the event is not of managed group interest', async function (ctx) {
  77. ctx.getUniqueManagedSubscriptionMemberOfMock.resolves({
  78. _id: subscriptionId,
  79. })
  80. await ctx.ProjectAuditLogHandler.promises.addEntry(
  81. projectId,
  82. 'any-event',
  83. userId,
  84. '0:0:0:0'
  85. )
  86. expect(ctx.createEntryMock).not.to.have.been.calledWithMatch({
  87. managedSubscriptionId: subscriptionId,
  88. })
  89. })
  90. it('adds multiple entries when the log involves multiple group subscriptions', async function (ctx) {
  91. ctx.getUniqueManagedSubscriptionMemberOfMock.onFirstCall().resolves({
  92. _id: subscriptionId,
  93. })
  94. ctx.getUniqueManagedSubscriptionMemberOfMock.onSecondCall().resolves({
  95. _id: subscriptionId2,
  96. })
  97. await ctx.ProjectAuditLogHandler.promises.addEntry(
  98. projectId,
  99. 'transfer-ownership',
  100. userId,
  101. '0:0:0:0',
  102. { previousOwnerId, newOwnerId }
  103. )
  104. expect(ctx.createEntryMock).to.have.been.calledTwice
  105. expect(ctx.createEntryMock).to.have.been.calledWithMatch({
  106. managedSubscriptionId: subscriptionId.toString(),
  107. })
  108. expect(ctx.createEntryMock).to.have.been.calledWithMatch({
  109. managedSubscriptionId: subscriptionId2.toString(),
  110. })
  111. })
  112. })
  113. describe('addEntryIfManaged', function () {
  114. describe('when the user is managed', function () {
  115. beforeEach(function (ctx) {
  116. ctx.getUniqueManagedSubscriptionMemberOfMock.resolves({
  117. _id: subscriptionId,
  118. })
  119. })
  120. it('adds an entry in the DB if the event is of interest of managed groups ', async function (ctx) {
  121. await ctx.ProjectAuditLogHandler.promises.addEntryIfManaged(
  122. projectId,
  123. 'accept-invite', // this event logs managedSubscriptionId when available
  124. userId,
  125. '0:0:0:0'
  126. )
  127. expect(ctx.createEntryMock).to.have.been.calledOnceWith({
  128. operation: 'accept-invite',
  129. projectId,
  130. initiatorId: userId,
  131. ipAddress: '0:0:0:0',
  132. info: {},
  133. managedSubscriptionId: subscriptionId.toString(),
  134. })
  135. })
  136. it('does not add an entry in the DB when the event is not of interest of managed groups ', async function (ctx) {
  137. await ctx.ProjectAuditLogHandler.promises.addEntryIfManaged(
  138. projectId,
  139. 'foo',
  140. userId,
  141. '0:0:0:0'
  142. )
  143. expect(ctx.createEntryMock).not.to.have.been.called
  144. })
  145. })
  146. describe('when the user is not managed', function () {
  147. it('does not add an entry in the DB ', async function (ctx) {
  148. await ctx.ProjectAuditLogHandler.promises.addEntryIfManaged(
  149. projectId,
  150. 'accept-invite', // this event logs managedSubscriptionId when available
  151. userId,
  152. '0:0:0:0'
  153. )
  154. expect(ctx.createEntryMock).not.to.have.been.called
  155. })
  156. })
  157. it('adds multiple entries when the log involves multiple group subscriptions', async function (ctx) {
  158. ctx.getUniqueManagedSubscriptionMemberOfMock.onFirstCall().resolves({
  159. _id: subscriptionId,
  160. })
  161. ctx.getUniqueManagedSubscriptionMemberOfMock.onSecondCall().resolves({
  162. _id: subscriptionId2,
  163. })
  164. await ctx.ProjectAuditLogHandler.promises.addEntryIfManaged(
  165. projectId,
  166. 'transfer-ownership',
  167. userId,
  168. '0:0:0:0',
  169. { previousOwnerId, newOwnerId }
  170. )
  171. expect(ctx.createEntryMock).to.have.been.calledTwice
  172. expect(ctx.createEntryMock).to.have.been.calledWithMatch({
  173. managedSubscriptionId: subscriptionId.toString(),
  174. })
  175. expect(ctx.createEntryMock).to.have.been.calledWithMatch({
  176. managedSubscriptionId: subscriptionId2.toString(),
  177. })
  178. })
  179. })
  180. })