Pārlūkot izejas kodu

[web] Project collaboration events for Group Audit Logs (#30055)

* [web] Project collaboration events for Group Audit Logs

* Using `role` instead of `privileges` for `(send|revoke)-invite` audit log

GitOrigin-RevId: 88961afcc0580243ba9c8ab661b8fc1ca127775e
Miguel Serrano 6 mēneši atpakaļ
vecāks
revīzija
05d04e864d

+ 2 - 14
services/web/app/src/Features/Collaborators/CollaboratorsHandler.mjs

@@ -7,6 +7,7 @@ import ContactManager from '../Contacts/ContactManager.mjs'
 import PrivilegeLevels from '../Authorization/PrivilegeLevels.mjs'
 import TpdsProjectFlusher from '../ThirdPartyDataStore/TpdsProjectFlusher.mjs'
 import CollaboratorsGetter from './CollaboratorsGetter.mjs'
+import CollaboratorsInviteHelper from './CollaboratorsInviteHelper.mjs'
 import Errors from '../Errors/Errors.js'
 import TpdsUpdateSender from '../ThirdPartyDataStore/TpdsUpdateSender.mjs'
 import EditorRealTimeController from '../Editor/EditorRealTimeController.mjs'
@@ -361,7 +362,7 @@ async function setCollaboratorPrivilegeLevel(
     auditInfo.ipAddress,
     {
       userId,
-      role: _privilegeLevelToRole(privilegeLevel),
+      role: CollaboratorsInviteHelper.privilegeLevelToRole(privilegeLevel),
     }
   )
 
@@ -374,19 +375,6 @@ async function setCollaboratorPrivilegeLevel(
   }
 }
 
-function _privilegeLevelToRole(privilegeLevel) {
-  switch (privilegeLevel) {
-    case 'readOnly':
-      return 'Viewer'
-    case 'readAndWrite':
-      return 'Editor'
-    case 'review':
-      return 'Reviewer'
-    default:
-      return privilegeLevel
-  }
-}
-
 async function userIsTokenMember(userId, projectId) {
   if (!userId) {
     return false

+ 3 - 2
services/web/app/src/Features/Collaborators/CollaboratorsInviteController.mjs

@@ -4,6 +4,7 @@ import UserGetter from '../User/UserGetter.mjs'
 import CollaboratorsGetter from './CollaboratorsGetter.mjs'
 import CollaboratorsInviteHandler from './CollaboratorsInviteHandler.mjs'
 import CollaboratorsInviteGetter from './CollaboratorsInviteGetter.mjs'
+import CollaboratorsInviteHelper from './CollaboratorsInviteHelper.mjs'
 import logger from '@overleaf/logger'
 import Settings from '@overleaf/settings'
 import EmailHelper from '../Helpers/EmailHelper.mjs'
@@ -171,7 +172,7 @@ async function inviteToProject(req, res) {
     req.ip,
     {
       inviteId: invite._id,
-      privileges,
+      role: CollaboratorsInviteHelper.privilegeLevelToRole(invite.privileges),
     }
   )
 
@@ -202,7 +203,7 @@ async function revokeInvite(req, res) {
       req.ip,
       {
         inviteId: invite._id,
-        privileges: invite.privileges,
+        role: CollaboratorsInviteHelper.privilegeLevelToRole(invite.privileges),
       }
     )
     EditorRealTimeController.emitToRoom(

+ 14 - 0
services/web/app/src/Features/Collaborators/CollaboratorsInviteHelper.mjs

@@ -11,7 +11,21 @@ function hashInviteToken(token) {
     .digest('hex')
 }
 
+function privilegeLevelToRole(privilegeLevel) {
+  switch (privilegeLevel) {
+    case 'readOnly':
+      return 'Viewer'
+    case 'readAndWrite':
+      return 'Editor'
+    case 'review':
+      return 'Reviewer'
+    default:
+      return privilegeLevel
+  }
+}
+
 export default {
   generateToken,
   hashInviteToken,
+  privilegeLevelToRole,
 }

+ 3 - 0
services/web/app/src/Features/Project/ProjectAuditLogHandler.mjs

@@ -19,6 +19,9 @@ const MANAGED_GROUP_PROJECT_EVENTS = [
   'project-history-version-restored',
   'project-history-version-downloaded',
   'transfer-ownership',
+  'remove-collaborator',
+  'revoke-invite',
+  'toggle-access-level',
   'project-downloaded',
 ]
 

+ 19 - 4
services/web/test/unit/src/Collaborators/CollaboratorsInviteController.test.mjs

@@ -22,6 +22,7 @@ describe('CollaboratorsInviteController', function () {
     ctx.tokenHmac = 'some-hmac-token'
     ctx.targetEmail = 'user@example.com'
     ctx.privileges = 'readAndWrite'
+    ctx.role = 'Editor'
     ctx.projectOwner = {
       _id: 'project-owner-id',
       email: 'project-owner@example.com',
@@ -366,7 +367,7 @@ describe('CollaboratorsInviteController', function () {
           ctx.req.ip,
           {
             inviteId: ctx.invite._id,
-            privileges: ctx.privileges,
+            role: ctx.role,
           }
         )
       })
@@ -381,6 +382,7 @@ describe('CollaboratorsInviteController', function () {
         beforeEach(async function (ctx) {
           await new Promise(resolve => {
             ctx.privileges = 'readAndWrite'
+            ctx.role = 'Editor'
             ctx.CollaboratorsInviteController._checkShouldInviteEmail = sinon
               .stub()
               .resolves(true)
@@ -421,10 +423,23 @@ describe('CollaboratorsInviteController', function () {
 
       describe('readOnly collaborator (always allowed)', function () {
         beforeEach(async function (ctx) {
+          ctx.privileges = 'readOnly'
+          ctx.role = 'Viewer'
+          // Update the invite data to reflect the new privileges
+          ctx.invite.privileges = ctx.privileges
+          ctx.inviteReducedData = _.pick(ctx.invite, [
+            '_id',
+            'email',
+            'privileges',
+          ])
+          ctx.CollaboratorsInviteHandler.promises.inviteToProject.resolves(
+            ctx.inviteReducedData
+          )
+
           await new Promise(resolve => {
             ctx.req.body = {
               email: ctx.targetEmail,
-              privileges: (ctx.privileges = 'readOnly'),
+              privileges: ctx.privileges,
             }
             ctx.CollaboratorsInviteController._checkShouldInviteEmail = sinon
               .stub()
@@ -492,7 +507,7 @@ describe('CollaboratorsInviteController', function () {
             ctx.req.ip,
             {
               inviteId: ctx.invite._id,
-              privileges: ctx.privileges,
+              role: ctx.role,
             }
           )
         })
@@ -1389,7 +1404,7 @@ describe('CollaboratorsInviteController', function () {
           ctx.req.ip,
           {
             inviteId: ctx.invite._id,
-            privileges: ctx.privileges,
+            role: ctx.role,
           }
         )
       })