[web] Add collaboratorEmail data to group audit logs (#32644)

Added `collaboratorEmail`, extracted wither from the invite, or the User record for the `remove-collaborator` event.

GitOrigin-RevId: c6465ad6633a244ac58a487481a67abbb768ba78
This commit is contained in:
Miguel Serrano
2026-04-09 10:31:39 +02:00
committed by Copybot
parent 7db4dfd780
commit c83d37437d
4 changed files with 38 additions and 4 deletions

View File

@@ -17,6 +17,7 @@ import LimitationsManager from '../Subscription/LimitationsManager.mjs'
import PrivilegeLevels from '../Authorization/PrivilegeLevels.mjs'
import { z, zz, parseReq } from '../../infrastructure/Validation.mjs'
import Features from '../../infrastructure/Features.mjs'
import UserGetter from '../User/UserGetter.mjs'
const { hasAdminAccess } = AdminAuthorizationHelper
const ObjectId = mongodb.ObjectId
@@ -39,12 +40,20 @@ async function removeUserFromProject(req, res, next) {
members: true,
})
const removedUser = await UserGetter.promises.getUser(
{ _id: userId },
{ email: 1 }
)
ProjectAuditLogHandler.addEntryInBackground(
projectId,
'remove-collaborator',
sessionUserId,
req.ip,
{ userId }
{
userId,
collaboratorEmail: removedUser?.email,
}
)
res.sendStatus(204)

View File

@@ -204,6 +204,7 @@ async function revokeInvite(req, res) {
req.ip,
{
inviteId: invite._id,
collaboratorEmail: invite.email,
role: CollaboratorsInviteHelper.privilegeLevelToRole(invite.privileges),
}
)
@@ -380,6 +381,7 @@ async function acceptInvite(req, res) {
req.ip,
{
inviteId: invite._id,
collaboratorEmail: invite.email,
privileges: invite.privileges,
}
)

View File

@@ -19,7 +19,7 @@ describe('CollaboratorsController', function () {
ctx.res = new MockResponse(vi)
ctx.req = new MockRequest(vi)
ctx.user = { _id: new ObjectId() }
ctx.user = { _id: new ObjectId(), email: 'user@example.com' }
ctx.projectId = new ObjectId()
ctx.callback = sinon.stub()
@@ -51,6 +51,13 @@ describe('CollaboratorsController', function () {
getSessionUser: sinon.stub().returns(ctx.user),
getLoggedInUserId: sinon.stub().returns(ctx.user._id),
}
ctx.UserGetter = {
promises: {
getAllInvitedMembers: sinon.stub(),
getUser: sinon.stub().resolves(ctx.user),
},
}
ctx.OwnershipTransferHandler = {
promises: {
transferOwnership: sinon.stub().resolves(),
@@ -133,6 +140,10 @@ describe('CollaboratorsController', function () {
})
)
vi.doMock('../../../../app/src/Features/User/UserGetter.mjs', () => ({
default: ctx.UserGetter,
}))
vi.doMock(
'../../../../app/src/Features/TokenAccess/TokenAccessHandler.mjs',
() => ({
@@ -207,13 +218,23 @@ describe('CollaboratorsController', function () {
)
})
it('should look up the collaborator email', function (ctx) {
expect(ctx.UserGetter.promises.getUser).to.have.been.calledWith(
{ _id: ctx.user._id },
{ email: 1 }
)
})
it('should write a project audit log', function (ctx) {
ctx.ProjectAuditLogHandler.addEntryInBackground.should.have.been.calledWith(
ctx.projectId,
'remove-collaborator',
ctx.user._id,
ctx.req.ip,
{ userId: ctx.user._id }
{
userId: ctx.user._id,
collaboratorEmail: 'user@example.com',
}
)
})
})

View File

@@ -70,7 +70,7 @@ describe('CollaboratorsInviteController', function () {
ctx.UserGetter = {
promises: {
getUserByAnyEmail: sinon.stub(),
getUser: sinon.stub(),
getUser: sinon.stub().resolves(ctx.currentUser),
},
}
@@ -1600,6 +1600,7 @@ describe('CollaboratorsInviteController', function () {
ctx.req.ip,
{
inviteId: ctx.invite._id,
collaboratorEmail: ctx.invite.email,
role: ctx.role,
}
)
@@ -1689,6 +1690,7 @@ describe('CollaboratorsInviteController', function () {
ctx.req.ip,
{
inviteId: ctx.invite._id,
collaboratorEmail: ctx.invite.email,
privileges: ctx.privileges,
}
)