LibreChat/config/migrate-terms-timestamp.js

100 lines
3 KiB
JavaScript

const path = require('path');
const mongoose = require('mongoose');
const { User } = require('@librechat/data-schemas').createModels(mongoose);
require('module-alias')({ base: path.resolve(__dirname, '..', 'api') });
const { askQuestion, silentExit } = require('./helpers');
const connect = require('./connect');
/**
* Migration script for Terms Acceptance Timestamp Tracking
*
* This script migrates existing users who have termsAccepted: true but no termsAcceptedAt timestamp.
* For these users, it sets termsAcceptedAt to their account creation date (createdAt) as a fallback.
*
* Usage: npm run migrate:terms-timestamp
*/
(async () => {
await connect();
console.purple('--------------------------');
console.purple('Migrate Terms Acceptance Timestamps');
console.purple('--------------------------');
// Count users that need migration
const usersToMigrate = await User.countDocuments({
termsAccepted: true,
$or: [{ termsAcceptedAt: null }, { termsAcceptedAt: { $exists: false } }],
});
if (usersToMigrate === 0) {
console.green(
'No users need migration. All users with termsAccepted: true already have a termsAcceptedAt timestamp.',
);
silentExit(0);
}
console.yellow(
`Found ${usersToMigrate} user(s) with termsAccepted: true but no termsAcceptedAt timestamp.`,
);
console.yellow(
'These users will have their termsAcceptedAt set to their account creation date (createdAt).',
);
const confirm = await askQuestion('Are you sure you want to proceed? (y/n): ');
if (confirm.toLowerCase() !== 'y') {
console.yellow('Operation cancelled.');
silentExit(0);
}
try {
// Find all users that need migration and update them
const cursor = User.find({
termsAccepted: true,
$or: [{ termsAcceptedAt: null }, { termsAcceptedAt: { $exists: false } }],
}).cursor();
let migratedCount = 0;
let errorCount = 0;
for await (const user of cursor) {
try {
// Use createdAt as fallback for termsAcceptedAt
const termsAcceptedAt = user.createdAt || new Date();
await User.updateOne({ _id: user._id }, { $set: { termsAcceptedAt } });
migratedCount++;
if (migratedCount % 100 === 0) {
console.yellow(`Migrated ${migratedCount} users...`);
}
} catch (error) {
console.red(`Error migrating user ${user._id}: ${error.message}`);
errorCount++;
}
}
console.green(`Migration complete!`);
console.green(`Successfully migrated: ${migratedCount} user(s)`);
if (errorCount > 0) {
console.red(`Errors encountered: ${errorCount}`);
}
} catch (error) {
console.red('Error during migration:', error);
silentExit(1);
}
silentExit(0);
})();
process.on('uncaughtException', (err) => {
if (!err.message.includes('fetch failed')) {
console.error('There was an uncaught error:');
console.error(err);
}
if (err.message.includes('fetch failed')) {
return;
} else {
process.exit(1);
}
});