Merge pull request #23131 from overleaf/kh-teardown-link-sharing-split-tests
[web] tear down link sharing split tests GitOrigin-RevId: 449e9f368405aea1500035269428e7ae0c37d8fb
This commit is contained in:
@@ -13,8 +13,6 @@ import { expressify } from '@overleaf/promise-utils'
|
||||
import { hasAdminAccess } from '../Helpers/AdminAuthorizationHelper.js'
|
||||
import TokenAccessHandler from '../TokenAccess/TokenAccessHandler.js'
|
||||
import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
|
||||
import ProjectGetter from '../Project/ProjectGetter.js'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import LimitationsManager from '../Subscription/LimitationsManager.js'
|
||||
import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
|
||||
|
||||
@@ -83,24 +81,14 @@ async function setCollaboratorInfo(req, res, next) {
|
||||
const { privilegeLevel } = req.body
|
||||
|
||||
if (privilegeLevel !== PrivilegeLevels.READ_ONLY) {
|
||||
const project = await ProjectGetter.promises.getProject(projectId, {
|
||||
owner_ref: 1,
|
||||
})
|
||||
const linkSharingChanges =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-warning'
|
||||
)
|
||||
const allowed =
|
||||
await LimitationsManager.promises.canAddXEditCollaborators(projectId, 1)
|
||||
if (linkSharingChanges?.variant === 'active') {
|
||||
if (!allowed) {
|
||||
return HttpErrorHandler.forbidden(
|
||||
req,
|
||||
res,
|
||||
'edit collaborator limit reached'
|
||||
)
|
||||
}
|
||||
if (!allowed) {
|
||||
return HttpErrorHandler.forbidden(
|
||||
req,
|
||||
res,
|
||||
'edit collaborator limit reached'
|
||||
)
|
||||
}
|
||||
}
|
||||
await CollaboratorsHandler.promises.setCollaboratorPrivilegeLevel(
|
||||
|
||||
@@ -15,7 +15,6 @@ import { expressify } from '@overleaf/promise-utils'
|
||||
import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
|
||||
import Errors from '../Errors/Errors.js'
|
||||
import AuthenticationController from '../Authentication/AuthenticationController.js'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
|
||||
|
||||
// This rate limiter allows a different number of requests depending on the
|
||||
@@ -98,28 +97,12 @@ async function inviteToProject(req, res) {
|
||||
|
||||
logger.debug({ projectId, email, sendingUserId }, 'inviting to project')
|
||||
|
||||
const project = await ProjectGetter.promises.getProject(projectId, {
|
||||
owner_ref: 1,
|
||||
})
|
||||
const linkSharingChanges =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-warning'
|
||||
)
|
||||
|
||||
let allowed = false
|
||||
if (linkSharingChanges?.variant === 'active') {
|
||||
// if link-sharing-warning is active, can always invite read-only collaborators
|
||||
if (privileges === PrivilegeLevels.READ_ONLY) {
|
||||
allowed = true
|
||||
} else {
|
||||
allowed = await LimitationsManager.promises.canAddXEditCollaborators(
|
||||
projectId,
|
||||
1
|
||||
)
|
||||
}
|
||||
// can always invite read-only collaborators
|
||||
if (privileges === PrivilegeLevels.READ_ONLY) {
|
||||
allowed = true
|
||||
} else {
|
||||
allowed = await LimitationsManager.promises.canAddXCollaborators(
|
||||
allowed = await LimitationsManager.promises.canAddXEditCollaborators(
|
||||
projectId,
|
||||
1
|
||||
)
|
||||
|
||||
@@ -9,7 +9,6 @@ import UserGetter from '../User/UserGetter.js'
|
||||
import ProjectGetter from '../Project/ProjectGetter.js'
|
||||
import NotificationsBuilder from '../Notifications/NotificationsBuilder.js'
|
||||
import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import LimitationsManager from '../Subscription/LimitationsManager.js'
|
||||
import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
|
||||
import _ from 'lodash'
|
||||
@@ -148,14 +147,8 @@ const CollaboratorsInviteHandler = {
|
||||
const project = await ProjectGetter.promises.getProject(projectId, {
|
||||
owner_ref: 1,
|
||||
})
|
||||
const linkSharingEnforcement =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-enforcement'
|
||||
)
|
||||
const pendingEditor =
|
||||
invite.privileges === PrivilegeLevels.READ_AND_WRITE &&
|
||||
linkSharingEnforcement?.variant === 'active' &&
|
||||
!(await LimitationsManager.promises.canAcceptEditCollaboratorInvite(
|
||||
project._id
|
||||
))
|
||||
|
||||
@@ -485,52 +485,32 @@ const _ProjectController = {
|
||||
anonRequestToken
|
||||
)
|
||||
|
||||
const [
|
||||
linkSharingChanges,
|
||||
linkSharingEnforcement,
|
||||
reviewerRoleAssignment,
|
||||
] = await Promise.all([
|
||||
SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-warning'
|
||||
),
|
||||
SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-enforcement'
|
||||
),
|
||||
SplitTestHandler.promises.getAssignmentForUser(
|
||||
const reviewerRoleAssignment =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'reviewer-role'
|
||||
),
|
||||
])
|
||||
)
|
||||
|
||||
if (linkSharingChanges?.variant === 'active') {
|
||||
if (linkSharingEnforcement?.variant === 'active') {
|
||||
await Modules.promises.hooks.fire(
|
||||
'enforceCollaboratorLimit',
|
||||
await Modules.promises.hooks.fire('enforceCollaboratorLimit', projectId)
|
||||
if (isTokenMember) {
|
||||
// Check explicitly that the user is in read write token refs, while this could be inferred
|
||||
// from the privilege level, the privilege level of token members might later be restricted
|
||||
const isReadWriteTokenMember =
|
||||
await CollaboratorsGetter.promises.userIsReadWriteTokenMember(
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
}
|
||||
if (isTokenMember) {
|
||||
// Check explicitly that the user is in read write token refs, while this could be inferred
|
||||
// from the privilege level, the privilege level of token members might later be restricted
|
||||
const isReadWriteTokenMember =
|
||||
await CollaboratorsGetter.promises.userIsReadWriteTokenMember(
|
||||
if (isReadWriteTokenMember) {
|
||||
// Check for an edge case where a user is both in read write token access refs but also
|
||||
// an invited read write member. Ensure they are not redirected to the sharing updates page
|
||||
// We could also delete the token access ref if the user is already a member of the project
|
||||
const isInvitedReadWriteMember =
|
||||
await CollaboratorsGetter.promises.isUserInvitedReadWriteMemberOfProject(
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
if (isReadWriteTokenMember) {
|
||||
// Check for an edge case where a user is both in read write token access refs but also
|
||||
// an invited read write member. Ensure they are not redirected to the sharing updates page
|
||||
// We could also delete the token access ref if the user is already a member of the project
|
||||
const isInvitedReadWriteMember =
|
||||
await CollaboratorsGetter.promises.isUserInvitedReadWriteMemberOfProject(
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
if (!isInvitedReadWriteMember) {
|
||||
return res.redirect(`/project/${projectId}/sharing-updates`)
|
||||
}
|
||||
if (!isInvitedReadWriteMember) {
|
||||
return res.redirect(`/project/${projectId}/sharing-updates`)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -589,9 +569,6 @@ const _ProjectController = {
|
||||
const exceedAtLimit = planLimit > -1 && namedEditors >= planLimit
|
||||
const projectOpenedSegmentation = {
|
||||
projectId: project._id,
|
||||
// temporary link sharing segmentation:
|
||||
linkSharingWarning: linkSharingChanges?.variant,
|
||||
linkSharingEnforcement: linkSharingEnforcement?.variant,
|
||||
namedEditors,
|
||||
pendingEditors,
|
||||
tokenEditors: project.tokenAccessReadAndWrite_refs?.length || 0,
|
||||
@@ -833,8 +810,6 @@ const _ProjectController = {
|
||||
useOpenTelemetry: Settings.useOpenTelemetryClient,
|
||||
hasTrackChangesFeature: Features.hasFeature('track-changes'),
|
||||
projectTags,
|
||||
linkSharingWarning: linkSharingChanges?.variant === 'active',
|
||||
linkSharingEnforcement: linkSharingEnforcement?.variant === 'active',
|
||||
usedLatex:
|
||||
// only use the usedLatex value if the split test is enabled
|
||||
splitTestAssignments['default-visual-for-beginners']?.variant ===
|
||||
|
||||
@@ -8,7 +8,6 @@ import { expressify } from '@overleaf/promise-utils'
|
||||
import AuthorizationManager from '../Authorization/AuthorizationManager.js'
|
||||
import PrivilegeLevels from '../Authorization/PrivilegeLevels.js'
|
||||
import ProjectAuditLogHandler from '../Project/ProjectAuditLogHandler.js'
|
||||
import SplitTestHandler from '../SplitTests/SplitTestHandler.js'
|
||||
import CollaboratorsInviteHandler from '../Collaborators/CollaboratorsInviteHandler.mjs'
|
||||
import CollaboratorsHandler from '../Collaborators/CollaboratorsHandler.js'
|
||||
import EditorRealTimeController from '../Editor/EditorRealTimeController.js'
|
||||
@@ -317,108 +316,60 @@ async function grantTokenAccessReadAndWrite(req, res, next) {
|
||||
return next(new Errors.NotFoundError())
|
||||
}
|
||||
|
||||
const linkSharingChanges =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-warning'
|
||||
)
|
||||
|
||||
if (linkSharingChanges?.variant === 'active') {
|
||||
if (!confirmedByUser) {
|
||||
return res.json({
|
||||
requireAccept: {
|
||||
linkSharingChanges: true,
|
||||
projectName: project.name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const linkSharingEnforcement =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-enforcement'
|
||||
)
|
||||
const pendingEditor =
|
||||
linkSharingEnforcement?.variant === 'active' &&
|
||||
!(await LimitationsManager.promises.canAcceptEditCollaboratorInvite(
|
||||
project._id
|
||||
))
|
||||
await ProjectAuditLogHandler.promises.addEntry(
|
||||
project._id,
|
||||
'accept-via-link-sharing',
|
||||
userId,
|
||||
req.ip,
|
||||
{
|
||||
privileges: pendingEditor ? 'readOnly' : 'readAndWrite',
|
||||
...(pendingEditor && { pendingEditor: true }),
|
||||
}
|
||||
)
|
||||
AnalyticsManager.recordEventForUserInBackground(
|
||||
userId,
|
||||
'project-joined',
|
||||
{
|
||||
mode: pendingEditor ? 'read-only' : 'read-write',
|
||||
projectId: project._id.toString(),
|
||||
...(pendingEditor && { pendingEditor: true }),
|
||||
}
|
||||
)
|
||||
await CollaboratorsHandler.promises.addUserIdToProject(
|
||||
project._id,
|
||||
undefined,
|
||||
userId,
|
||||
pendingEditor
|
||||
? PrivilegeLevels.READ_ONLY
|
||||
: PrivilegeLevels.READ_AND_WRITE,
|
||||
{ pendingEditor }
|
||||
)
|
||||
|
||||
// remove pending invite and notification
|
||||
const userEmails =
|
||||
await UserGetter.promises.getUserConfirmedEmails(userId)
|
||||
await CollaboratorsInviteHandler.promises.revokeInviteForUser(
|
||||
project._id,
|
||||
userEmails
|
||||
)
|
||||
// Should be a noop if the user is already a member,
|
||||
// and would redirect transparently into the project.
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project._id,
|
||||
'project:membership:changed',
|
||||
{ members: true, invites: true }
|
||||
)
|
||||
|
||||
if (!confirmedByUser) {
|
||||
return res.json({
|
||||
redirect: `/project/${project._id}`,
|
||||
})
|
||||
} else {
|
||||
if (!confirmedByUser) {
|
||||
return res.json({
|
||||
requireAccept: {
|
||||
projectName: project.name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
if (!project.tokenAccessReadAndWrite_refs.some(id => id.equals(userId))) {
|
||||
await ProjectAuditLogHandler.promises.addEntry(
|
||||
project._id,
|
||||
'join-via-token',
|
||||
userId,
|
||||
req.ip,
|
||||
{ privileges: 'readAndWrite' }
|
||||
)
|
||||
}
|
||||
|
||||
await TokenAccessHandler.promises.addReadAndWriteUserToProject(
|
||||
userId,
|
||||
project._id
|
||||
)
|
||||
|
||||
return res.json({
|
||||
redirect: `/project/${project._id}`,
|
||||
tokenAccessGranted: tokenType,
|
||||
requireAccept: {
|
||||
projectName: project.name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
const pendingEditor =
|
||||
!(await LimitationsManager.promises.canAcceptEditCollaboratorInvite(
|
||||
project._id
|
||||
))
|
||||
await ProjectAuditLogHandler.promises.addEntry(
|
||||
project._id,
|
||||
'accept-via-link-sharing',
|
||||
userId,
|
||||
req.ip,
|
||||
{
|
||||
privileges: pendingEditor ? 'readOnly' : 'readAndWrite',
|
||||
...(pendingEditor && { pendingEditor: true }),
|
||||
}
|
||||
)
|
||||
AnalyticsManager.recordEventForUserInBackground(userId, 'project-joined', {
|
||||
mode: pendingEditor ? 'read-only' : 'read-write',
|
||||
projectId: project._id.toString(),
|
||||
...(pendingEditor && { pendingEditor: true }),
|
||||
})
|
||||
await CollaboratorsHandler.promises.addUserIdToProject(
|
||||
project._id,
|
||||
undefined,
|
||||
userId,
|
||||
pendingEditor
|
||||
? PrivilegeLevels.READ_ONLY
|
||||
: PrivilegeLevels.READ_AND_WRITE,
|
||||
{ pendingEditor }
|
||||
)
|
||||
|
||||
// remove pending invite and notification
|
||||
const userEmails = await UserGetter.promises.getUserConfirmedEmails(userId)
|
||||
await CollaboratorsInviteHandler.promises.revokeInviteForUser(
|
||||
project._id,
|
||||
userEmails
|
||||
)
|
||||
// Should be a noop if the user is already a member,
|
||||
// and would redirect transparently into the project.
|
||||
EditorRealTimeController.emitToRoom(
|
||||
project._id,
|
||||
'project:membership:changed',
|
||||
{ members: true, invites: true }
|
||||
)
|
||||
|
||||
return res.json({
|
||||
redirect: `/project/${project._id}`,
|
||||
})
|
||||
} catch (err) {
|
||||
return next(
|
||||
OError.tag(
|
||||
@@ -516,14 +467,6 @@ async function ensureUserCanUseSharingUpdatesConsentPage(req, res, next) {
|
||||
if (!project) {
|
||||
throw new Errors.NotFoundError()
|
||||
}
|
||||
const linkSharingChanges =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-warning'
|
||||
)
|
||||
if (linkSharingChanges?.variant !== 'active') {
|
||||
return AsyncFormHelper.redirect(req, res, `/project/${projectId}`)
|
||||
}
|
||||
const isReadWriteTokenMember =
|
||||
await CollaboratorsGetter.promises.userIsReadWriteTokenMember(
|
||||
userId,
|
||||
@@ -567,13 +510,7 @@ async function moveReadWriteToCollaborators(req, res, next) {
|
||||
userId,
|
||||
projectId
|
||||
)
|
||||
const linkSharingEnforcement =
|
||||
await SplitTestHandler.promises.getAssignmentForUser(
|
||||
project.owner_ref,
|
||||
'link-sharing-enforcement'
|
||||
)
|
||||
const pendingEditor =
|
||||
linkSharingEnforcement?.variant === 'active' &&
|
||||
!(await LimitationsManager.promises.canAcceptEditCollaboratorInvite(
|
||||
project._id
|
||||
))
|
||||
|
||||
Reference in New Issue
Block a user