Ensure track changes is enabled for reviewers when switching roles (#22645)

* Ensure track changes is enabled for reviewers when switching roles

* update track_changes.${userId} if track_changes is an object

GitOrigin-RevId: 3e803f4d475dbb67ff85b30095307ea58a07b2bc
This commit is contained in:
Domagoj Kriskovic
2025-01-09 10:50:23 +01:00
committed by Copybot
parent f152925e49
commit 001443c1a4
2 changed files with 140 additions and 49 deletions

View File

@@ -149,32 +149,12 @@ async function addUserIdToProject(
}
if (privilegeLevel === PrivilegeLevels.REVIEW) {
const trackChanges =
typeof project.track_changes === 'object' ? project.track_changes : {}
const trackChanges = await convertTrackChangesToExplicitFormat(
projectId,
project.track_changes
)
trackChanges[userId] = true
if (project.track_changes === true) {
// track changes are enabled for all
// we need to convert it to explicit format
const members =
await CollaboratorsGetter.promises.getMemberIdsWithPrivilegeLevels(
project
)
for (const { id, privilegeLevel } of members) {
if (
[
PrivilegeLevels.OWNER,
PrivilegeLevels.READ_AND_WRITE,
PrivilegeLevels.REVIEW,
].includes(privilegeLevel)
) {
trackChanges[id] = true
}
}
}
await Project.updateOne(
{ _id: projectId },
{ track_changes: trackChanges, $addToSet: level }
@@ -312,6 +292,22 @@ async function setCollaboratorPrivilegeLevel(
},
$addToSet: { reviewer_refs: userId },
}
const project = await ProjectGetter.promises.getProject(projectId, {
track_changes: true,
})
const newTrackChangesState = await convertTrackChangesToExplicitFormat(
projectId,
project.track_changes
)
if (newTrackChangesState[userId] !== true) {
newTrackChangesState[userId] = true
}
if (typeof project.track_changes === 'object') {
update.$set = { [`track_changes.${userId}`]: true }
} else {
update.$set = { track_changes: newTrackChangesState }
}
break
}
case PrivilegeLevels.READ_ONLY: {
@@ -334,6 +330,14 @@ async function setCollaboratorPrivilegeLevel(
if (mongoResponse.matchedCount === 0) {
throw new Errors.NotFoundError('project or collaborator not found')
}
if (update.$set?.track_changes) {
EditorRealTimeController.emitToRoom(
projectId,
'toggle-track-changes',
update.$set.track_changes
)
}
}
async function userIsTokenMember(userId, projectId) {
@@ -367,3 +371,37 @@ async function _flushProjects(projectIds) {
await TpdsProjectFlusher.promises.flushProjectToTpds(projectId)
}
}
async function convertTrackChangesToExplicitFormat(
projectId,
trackChangesState
) {
if (typeof trackChangesState === 'object') {
return { ...trackChangesState }
}
if (trackChangesState === true) {
// track changes are enabled for all
const members =
await CollaboratorsGetter.promises.getMemberIdsWithPrivilegeLevels(
projectId
)
const newTrackChangesState = {}
for (const { id, privilegeLevel } of members) {
if (
[
PrivilegeLevels.OWNER,
PrivilegeLevels.READ_AND_WRITE,
PrivilegeLevels.REVIEW,
].includes(privilegeLevel)
) {
newTrackChangesState[id] = true
}
}
return newTrackChangesState
}
return {}
}

View File

@@ -640,33 +640,86 @@ describe('CollaboratorsHandler', function () {
)
})
it('sets a collaborator to reviewer', async function () {
this.ProjectMock.expects('updateOne')
.withArgs(
{
_id: this.projectId,
$or: [
{ collaberator_refs: this.userId },
{ readOnly_refs: this.userId },
{ reviewer_refs: this.userId },
],
},
{
$addToSet: { reviewer_refs: this.userId },
$pull: {
readOnly_refs: this.userId,
collaberator_refs: this.userId,
pendingEditor_refs: this.userId,
describe('sets a collaborator to reviewer when track changes is enabled for everyone', function () {
beforeEach(function () {
this.ProjectGetter.promises.getProject = sinon.stub().resolves({
_id: new ObjectId(),
owner_ref: this.addingUserId,
name: 'Foo',
track_changes: true,
})
})
it('should correctly update the project', async function () {
this.ProjectMock.expects('updateOne')
.withArgs(
{
_id: this.projectId,
$or: [
{ collaberator_refs: this.userId },
{ readOnly_refs: this.userId },
{ reviewer_refs: this.userId },
],
},
}
{
$addToSet: { reviewer_refs: this.userId },
$set: { track_changes: { [this.userId]: true } },
$pull: {
readOnly_refs: this.userId,
collaberator_refs: this.userId,
pendingEditor_refs: this.userId,
},
}
)
.chain('exec')
.resolves({ matchedCount: 1 })
await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
this.projectId,
this.userId,
'review'
)
.chain('exec')
.resolves({ matchedCount: 1 })
await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
this.projectId,
this.userId,
'review'
)
})
})
describe('sets a collaborator to reviewer when track changes is not enabled for everyone', function () {
beforeEach(function () {
this.ProjectGetter.promises.getProject = sinon.stub().resolves({
_id: new ObjectId(),
owner_ref: this.addingUserId,
name: 'Foo',
track_changes: {
[this.userId]: true,
},
})
})
it('should correctly update the project', async function () {
this.ProjectMock.expects('updateOne')
.withArgs(
{
_id: this.projectId,
$or: [
{ collaberator_refs: this.userId },
{ readOnly_refs: this.userId },
{ reviewer_refs: this.userId },
],
},
{
$addToSet: { reviewer_refs: this.userId },
$set: { [`track_changes.${this.userId}`]: true },
$pull: {
readOnly_refs: this.userId,
collaberator_refs: this.userId,
pendingEditor_refs: this.userId,
},
}
)
.chain('exec')
.resolves({ matchedCount: 1 })
await this.CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
this.projectId,
this.userId,
'review'
)
})
})
it('sets a collaborator to read-only as a pendingEditor', async function () {