const mongoose = require('mongoose'); const fs = require('fs').promises; const path = require('path'); // Atlas MongoDB connection string const MONGODB_URI = 'mongodb+srv://nothingyu:wSg3lbO1PkHiRMq9@sandbox.ecysggv.mongodb.net/test?retryWrites=true&w=majority&appName=sandbox'; // Connect to MongoDB Atlas const connectDB = async () => { try { await mongoose.connect(MONGODB_URI); console.log('āœ… Connected to MongoDB Atlas'); } catch (error) { console.error('āŒ MongoDB connection error:', error); process.exit(1); } }; // Backup and Version Control System const backupVersionControl = { // Create comprehensive backup async createBackup(customBackupName = null) { try { const timestamp = new Date().toISOString().replace(/[:.]/g, '-'); const backupName = customBackupName || `comprehensive-backup-${timestamp}`; console.log(`šŸ’¾ Creating comprehensive backup: ${backupName}`); const collections = ['subtitles', 'sourcetexts', 'submissions', 'users', 'securitylogs']; const backupData = { metadata: { backupName, timestamp: new Date(), collections: collections, totalRecords: 0, version: '1.0', createdBy: 'system' }, data: {} }; // Export all collections for (const collection of collections) { try { const data = await mongoose.connection.db.collection(collection).find({}).toArray(); backupData.data[collection] = data; backupData.metadata.totalRecords += data.length; console.log(` šŸ“¦ Exported ${data.length} records from ${collection}`); } catch (error) { console.warn(` āš ļø Could not export ${collection}:`, error.message); } } // Save backup to file system const backupDir = path.join(__dirname, 'backups'); await fs.mkdir(backupDir, { recursive: true }); const backupPath = path.join(backupDir, `${backupName}.json`); await fs.writeFile(backupPath, JSON.stringify(backupData, null, 2)); // Create backup record in database const backupRecord = { backupName, timestamp: new Date(), collections: collections, totalRecords: backupData.metadata.totalRecords, filePath: backupPath, status: 'created', createdBy: 'system' }; // Save to backup collection const backupCollection = mongoose.connection.db.collection('backups'); await backupCollection.insertOne(backupRecord); console.log(`āœ… Backup created successfully: ${backupName}`); console.log(`šŸ“Š Total records: ${backupData.metadata.totalRecords}`); console.log(`šŸ’¾ File saved: ${backupPath}`); return backupName; } catch (error) { console.error('āŒ Error creating backup:', error); throw error; } }, // Restore from backup async restoreFromBackup(backupName) { try { console.log(`šŸ”„ Restoring from backup: ${backupName}`); // Load backup file const backupPath = path.join(__dirname, 'backups', `${backupName}.json`); const backupData = JSON.parse(await fs.readFile(backupPath, 'utf8')); console.log(`šŸ“Š Backup metadata:`, backupData.metadata); // Confirm restoration console.log('āš ļø This will overwrite existing data. Are you sure? (y/N)'); // In a real implementation, you'd get user confirmation here // Restore each collection for (const [collection, data] of Object.entries(backupData.data)) { try { // Clear existing data await mongoose.connection.db.collection(collection).deleteMany({}); // Insert backup data if (data.length > 0) { await mongoose.connection.db.collection(collection).insertMany(data); } console.log(` āœ… Restored ${data.length} records to ${collection}`); } catch (error) { console.error(` āŒ Error restoring ${collection}:`, error.message); } } console.log(`āœ… Restoration completed: ${backupName}`); } catch (error) { console.error('āŒ Error restoring from backup:', error); throw error; } }, // List available backups async listBackups() { try { console.log('šŸ“‹ Available backups:'); // List from database const backupCollection = mongoose.connection.db.collection('backups'); const dbBackups = await backupCollection.find({}).sort({ timestamp: -1 }).toArray(); if (dbBackups.length === 0) { console.log(' No backups found in database'); } else { console.log(' Database backups:'); dbBackups.forEach(backup => { console.log(` šŸ“¦ ${backup.backupName} (${backup.totalRecords} records, ${new Date(backup.timestamp).toLocaleString()})`); }); } // List from file system const backupDir = path.join(__dirname, 'backups'); try { const files = await fs.readdir(backupDir); const backupFiles = files.filter(file => file.endsWith('.json')); if (backupFiles.length > 0) { console.log(' File system backups:'); for (const file of backupFiles) { const filePath = path.join(backupDir, file); const stats = await fs.stat(filePath); console.log(` šŸ’¾ ${file} (${(stats.size / 1024).toFixed(2)} KB, ${stats.mtime.toLocaleString()})`); } } } catch (error) { console.log(' No backup directory found'); } } catch (error) { console.error('āŒ Error listing backups:', error); } }, // Version control for content changes async createVersionControl() { try { console.log('šŸ“ Creating version control system...'); const versionControlSchema = new mongoose.Schema({ documentId: { type: String, required: true }, collection: { type: String, required: true }, version: { type: Number, required: true }, changes: mongoose.Schema.Types.Mixed, timestamp: { type: Date, default: Date.now }, userId: String, commitMessage: String, previousVersion: Number, checksum: String }); const VersionControl = mongoose.model('VersionControl', versionControlSchema); // Create indexes for efficient querying await VersionControl.createIndexes(); console.log('āœ… Version control system created'); return VersionControl; } catch (error) { console.error('āŒ Error creating version control:', error); } }, // Track content changes async trackChange(collection, documentId, changes, userId, commitMessage) { try { const VersionControl = mongoose.model('VersionControl'); // Get current version const latestVersion = await VersionControl.findOne({ documentId, collection }).sort({ version: -1 }); const newVersion = (latestVersion?.version || 0) + 1; // Create version record await VersionControl.create({ documentId, collection, version: newVersion, changes, userId, commitMessage, previousVersion: latestVersion?.version || null, timestamp: new Date() }); console.log(`šŸ“ Version ${newVersion} created for ${collection}/${documentId}`); } catch (error) { console.error('āŒ Error tracking change:', error); } }, // Get content history async getContentHistory(collection, documentId) { try { const VersionControl = mongoose.model('VersionControl'); const history = await VersionControl.find({ documentId, collection }).sort({ version: -1 }); console.log(`šŸ“‹ Version history for ${collection}/${documentId}:`); history.forEach(version => { console.log(` v${version.version} (${new Date(version.timestamp).toLocaleString()}) - ${version.commitMessage}`); }); return history; } catch (error) { console.error('āŒ Error getting content history:', error); } }, // Automated backup scheduling async scheduleBackups() { try { console.log('ā° Setting up automated backup scheduling...'); const scheduleSchema = new mongoose.Schema({ scheduleType: { type: String, enum: ['daily', 'weekly', 'monthly'], required: true }, lastBackup: Date, nextBackup: Date, isActive: { type: Boolean, default: true }, createdBy: String }); const Schedule = mongoose.model('Schedule', scheduleSchema); // Create default daily backup schedule await Schedule.create({ scheduleType: 'daily', lastBackup: null, nextBackup: new Date(Date.now() + 24 * 60 * 60 * 1000), // Tomorrow isActive: true, createdBy: 'system' }); console.log('āœ… Automated backup schedule created (daily)'); } catch (error) { console.error('āŒ Error setting up backup scheduling:', error); } }, // Verify backup integrity async verifyBackupIntegrity(backupName) { try { console.log(`šŸ” Verifying backup integrity: ${backupName}`); const backupPath = path.join(__dirname, 'backups', `${backupName}.json`); const backupData = JSON.parse(await fs.readFile(backupPath, 'utf8')); let verifiedCount = 0; let failedCount = 0; // Verify each collection for (const [collection, data] of Object.entries(backupData.data)) { try { const currentCount = await mongoose.connection.db.collection(collection).countDocuments(); const backupCount = data.length; if (currentCount === backupCount) { verifiedCount++; console.log(` āœ… ${collection}: ${backupCount} records verified`); } else { failedCount++; console.log(` āŒ ${collection}: ${backupCount} in backup, ${currentCount} in database`); } } catch (error) { failedCount++; console.log(` āŒ ${collection}: verification failed`); } } console.log(`šŸ” Integrity verification complete:`); console.log(` - Verified: ${verifiedCount} collections`); console.log(` - Failed: ${failedCount} collections`); return { verifiedCount, failedCount }; } catch (error) { console.error('āŒ Error verifying backup integrity:', error); } } }; // Main function const main = async () => { try { console.log('šŸš€ Starting backup and version control system...'); // Create comprehensive backup const backupName = await backupVersionControl.createBackup(); // Create version control system await backupVersionControl.createVersionControl(); // Set up automated backups await backupVersionControl.scheduleBackups(); // List available backups await backupVersionControl.listBackups(); console.log('\nšŸŽ‰ Backup and version control system ready!'); console.log('\nšŸ“‹ Available functions:'); console.log(' - createBackup(): Create new backup'); console.log(' - restoreFromBackup(name): Restore from backup'); console.log(' - listBackups(): List available backups'); console.log(' - trackChange(): Track content changes'); console.log(' - getContentHistory(): Get version history'); console.log(' - verifyBackupIntegrity(): Verify backup integrity'); } catch (error) { console.error('āŒ Error in backup and version control system:', error); } finally { await mongoose.disconnect(); console.log('šŸ”Œ Disconnected from MongoDB'); } }; // Run the system connectDB().then(() => { main(); });