[web] add config option for project/user hard deletion delay (#27725)

GitOrigin-RevId: db8030d6c8a3cdf8490edafcfa436cdbcd80fc28
This commit is contained in:
Jakob Ackermann
2025-08-12 11:01:34 +02:00
committed by Copybot
parent e4b42705c3
commit 9f80a31d85
3 changed files with 21 additions and 8 deletions

View File

@@ -7,6 +7,7 @@ const { DeletedProject } = require('../../models/DeletedProject')
const { ProjectAuditLogEntry } = require('../../models/ProjectAuditLogEntry')
const Errors = require('../Errors/Errors')
const logger = require('@overleaf/logger')
const Settings = require('@overleaf/settings')
const DocumentUpdaterHandler = require('../DocumentUpdater/DocumentUpdaterHandler')
const TagsHandler = require('../Tags/TagsHandler')
const ProjectDetailsHandler = require('./ProjectDetailsHandler')
@@ -17,11 +18,9 @@ const EditorRealTimeController = require('../Editor/EditorRealTimeController')
const HistoryManager = require('../History/HistoryManager')
const FilestoreHandler = require('../FileStore/FileStoreHandler')
const ChatApiHandler = require('../Chat/ChatApiHandler')
const moment = require('moment')
const { promiseMapWithLimit } = require('@overleaf/promise-utils')
const { READ_PREFERENCE_SECONDARY } = require('../../infrastructure/mongodb')
const EXPIRE_PROJECTS_AFTER_DAYS = 90
const PROJECT_EXPIRATION_BATCH_SIZE = 10000
module.exports = {
@@ -92,7 +91,7 @@ async function expireDeletedProjectsAfterDuration() {
const deletedProjects = await DeletedProject.find(
{
'deleterData.deletedAt': {
$lt: new Date(moment().subtract(EXPIRE_PROJECTS_AFTER_DAYS, 'days')),
$lt: new Date(Date.now() - Settings.projectHardDeletionDelay),
},
project: { $type: 'object' },
},
@@ -106,7 +105,11 @@ async function expireDeletedProjectsAfterDuration() {
)
)
logger.info(
{ projectCount: projectIds.length },
{
projectCount: projectIds.length,
retentionPeriodInDays:
Settings.projectHardDeletionDelay / (1000 * 60 * 60 * 24),
},
'expiring batch of deleted projects'
)
try {

View File

@@ -1,6 +1,6 @@
const { callbackify } = require('util')
const logger = require('@overleaf/logger')
const moment = require('moment')
const Settings = require('@overleaf/settings')
const { User } = require('../../models/User')
const { DeletedUser } = require('../../models/DeletedUser')
const { UserAuditLogEntry } = require('../../models/UserAuditLogEntry')
@@ -113,10 +113,9 @@ async function expireDeletedUser(userId) {
}
async function expireDeletedUsersAfterDuration() {
const DURATION = 90
const deletedUsers = await DeletedUser.find({
'deleterData.deletedAt': {
$lt: new Date(moment().subtract(DURATION, 'days')),
$lt: new Date(Date.now() - Settings.userHardDeletionDelay),
},
user: { $type: 'object' },
}).exec()
@@ -125,7 +124,11 @@ async function expireDeletedUsersAfterDuration() {
return
}
logger.info(
{ deletedUsers: deletedUsers.length, retentionPeriodInDays: DURATION },
{
deletedUsers: deletedUsers.length,
retentionPeriodInDays:
Settings.userHardDeletionDelay / (1000 * 60 * 60 * 24),
},
'expiring batch of deleted users older than retention period'
)
try {

View File

@@ -709,6 +709,13 @@ module.exports = {
primary_email_check_expiration: 1000 * 60 * 60 * 24 * 90, // 90 days
userHardDeletionDelay:
parseInt(process.env.OVERLEAF_USER_HARD_DELETION_DELAY, 10) ||
1000 * 60 * 60 * 24 * 90, // 90 days
projectHardDeletionDelay:
parseInt(process.env.OVERLEAF_PROJECT_HARD_DELETION_DELAY, 10) ||
1000 * 60 * 60 * 24 * 90, // 90 days
// Maximum JSON size in HTTP requests
// We should be able to process twice the max doc length, to allow for
// - the doc content