ебать что это блять

This commit is contained in:
2026-03-20 16:08:38 +07:00
parent d969ac594e
commit 7123aac2cc
11 changed files with 1531 additions and 1196 deletions

102
src/services/backups.js Normal file
View File

@@ -0,0 +1,102 @@
const fs = require('fs');
const path = require('path');
const BACKUPS_DIR = path.join(__dirname, '..', '..', 'backups');
const USERS_FILE = path.join(__dirname, '..', '..', 'users.json');
const AUDIT_LOG_FILE = path.join(__dirname, '..', '..', 'audit.log');
function ensureBackupsDir() {
fs.mkdirSync(BACKUPS_DIR, { recursive: true });
}
function makeBackupFilename() {
const now = new Date().toISOString().replace(/[:.]/g, '-');
return `backup-${now}.json`;
}
async function createBackup(pool, actor = 'system') {
ensureBackupsDir();
const tablesResult = await pool.query(`
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'public'
ORDER BY table_name
`);
const tables = [];
for (const row of tablesResult.rows) {
const tableName = row.table_name;
const structure = await pool.query(`
SELECT
c.column_name AS name,
c.data_type AS type,
c.is_nullable AS nullable,
c.column_default AS default_value
FROM information_schema.columns c
WHERE c.table_name = $1 AND c.table_schema = 'public'
ORDER BY c.ordinal_position
`, [tableName]);
const data = await pool.query(`SELECT * FROM "${tableName}"`);
tables.push({
name: tableName,
structure: structure.rows,
rows: data.rows,
});
}
const backup = {
meta: {
createdAt: new Date().toISOString(),
createdBy: actor,
version: 1,
},
users: fs.existsSync(USERS_FILE) ? JSON.parse(fs.readFileSync(USERS_FILE, 'utf8')) : { users: [] },
audit: fs.existsSync(AUDIT_LOG_FILE)
? fs.readFileSync(AUDIT_LOG_FILE, 'utf8').split(/\r?\n/).filter(Boolean)
: [],
tables,
};
const filename = makeBackupFilename();
const filePath = path.join(BACKUPS_DIR, filename);
fs.writeFileSync(filePath, JSON.stringify(backup, null, 2), 'utf8');
return {
filename,
filePath,
size: fs.statSync(filePath).size,
createdAt: backup.meta.createdAt,
};
}
function listBackups() {
ensureBackupsDir();
return fs.readdirSync(BACKUPS_DIR)
.filter((name) => name.endsWith('.json'))
.map((name) => {
const filePath = path.join(BACKUPS_DIR, name);
const stats = fs.statSync(filePath);
return {
filename: name,
size: stats.size,
createdAt: stats.birthtime.toISOString(),
};
})
.sort((a, b) => b.createdAt.localeCompare(a.createdAt));
}
function getBackupPath(filename) {
const filePath = path.join(BACKUPS_DIR, filename);
if (!filePath.startsWith(BACKUPS_DIR) || !fs.existsSync(filePath)) {
throw new Error('Backup not found');
}
return filePath;
}
module.exports = {
BACKUPS_DIR,
createBackup,
getBackupPath,
listBackups,
};