syncification

This commit is contained in:
zadam
2020-06-20 12:31:38 +02:00
parent 30062d687f
commit 88348c560c
97 changed files with 1673 additions and 1700 deletions

View File

@@ -11,28 +11,28 @@ const attributeService = require('./attributes');
const cls = require('./cls');
const utils = require('./utils');
async function regularBackup() {
await periodBackup('lastDailyBackupDate', 'daily', 24 * 3600);
function regularBackup() {
periodBackup('lastDailyBackupDate', 'daily', 24 * 3600);
await periodBackup('lastWeeklyBackupDate', 'weekly', 7 * 24 * 3600);
periodBackup('lastWeeklyBackupDate', 'weekly', 7 * 24 * 3600);
await periodBackup('lastMonthlyBackupDate', 'monthly', 30 * 24 * 3600);
periodBackup('lastMonthlyBackupDate', 'monthly', 30 * 24 * 3600);
}
async function periodBackup(optionName, fileName, periodInSeconds) {
function periodBackup(optionName, fileName, periodInSeconds) {
const now = new Date();
const lastDailyBackupDate = dateUtils.parseDateTime(await optionService.getOption(optionName));
const lastDailyBackupDate = dateUtils.parseDateTime(optionService.getOption(optionName));
if (now.getTime() - lastDailyBackupDate.getTime() > periodInSeconds * 1000) {
await backupNow(fileName);
backupNow(fileName);
await optionService.setOption(optionName, dateUtils.utcNowDateTime());
optionService.setOption(optionName, dateUtils.utcNowDateTime());
}
}
const COPY_ATTEMPT_COUNT = 50;
async function copyFile(backupFile) {
function copyFile(backupFile) {
const sql = require('./sql');
try {
@@ -45,7 +45,7 @@ async function copyFile(backupFile) {
for (; attemptCount < COPY_ATTEMPT_COUNT && !success; attemptCount++) {
try {
await sql.executeWithoutTransaction(`VACUUM INTO '${backupFile}'`);
sql.executeWithoutTransaction(`VACUUM INTO '${backupFile}'`);
success = true;
} catch (e) {
@@ -60,10 +60,10 @@ async function copyFile(backupFile) {
async function backupNow(name) {
// we don't want to backup DB in the middle of sync with potentially inconsistent DB state
return await syncMutexService.doExclusively(async () => {
return await syncMutexService.doExclusively(() => {
const backupFile = `${dataDir.BACKUP_DIR}/backup-${name}.db`;
const success = await copyFile(backupFile);
const success = copyFile(backupFile);
if (success) {
log.info("Created backup at " + backupFile);
@@ -76,45 +76,45 @@ async function backupNow(name) {
});
}
async function anonymize() {
function anonymize() {
if (!fs.existsSync(dataDir.ANONYMIZED_DB_DIR)) {
fs.mkdirSync(dataDir.ANONYMIZED_DB_DIR, 0o700);
}
const anonymizedFile = dataDir.ANONYMIZED_DB_DIR + "/" + "anonymized-" + dateUtils.getDateTimeForFile() + ".db";
const success = await copyFile(anonymizedFile);
const success = copyFile(anonymizedFile);
if (!success) {
return { success: false };
}
const db = await sqlite.open({
const db = sqlite.open({
filename: anonymizedFile,
driver: sqlite3.Database
});
await db.run("UPDATE api_tokens SET token = 'API token value'");
await db.run("UPDATE notes SET title = 'title'");
await db.run("UPDATE note_contents SET content = 'text' WHERE content IS NOT NULL");
await db.run("UPDATE note_revisions SET title = 'title'");
await db.run("UPDATE note_revision_contents SET content = 'text' WHERE content IS NOT NULL");
db.run("UPDATE api_tokens SET token = 'API token value'");
db.run("UPDATE notes SET title = 'title'");
db.run("UPDATE note_contents SET content = 'text' WHERE content IS NOT NULL");
db.run("UPDATE note_revisions SET title = 'title'");
db.run("UPDATE note_revision_contents SET content = 'text' WHERE content IS NOT NULL");
// we want to delete all non-builtin attributes because they can contain sensitive names and values
// on the other hand builtin/system attrs should not contain any sensitive info
const builtinAttrs = attributeService.getBuiltinAttributeNames().map(name => "'" + utils.sanitizeSql(name) + "'").join(', ');
await db.run(`UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN(${builtinAttrs})`);
await db.run(`UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN (${builtinAttrs})`);
await db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");
await db.run(`UPDATE options SET value = 'anonymized' WHERE name IN
db.run(`UPDATE attributes SET name = 'name', value = 'value' WHERE type = 'label' AND name NOT IN(${builtinAttrs})`);
db.run(`UPDATE attributes SET name = 'name' WHERE type = 'relation' AND name NOT IN (${builtinAttrs})`);
db.run("UPDATE branches SET prefix = 'prefix' WHERE prefix IS NOT NULL");
db.run(`UPDATE options SET value = 'anonymized' WHERE name IN
('documentId', 'documentSecret', 'encryptedDataKey',
'passwordVerificationHash', 'passwordVerificationSalt',
'passwordDerivedKeySalt', 'username', 'syncServerHost', 'syncProxy')
AND value != ''`);
await db.run("VACUUM");
db.run("VACUUM");
await db.close();
db.close();
return {
success: true,
@@ -126,12 +126,10 @@ if (!fs.existsSync(dataDir.BACKUP_DIR)) {
fs.mkdirSync(dataDir.BACKUP_DIR, 0o700);
}
sqlInit.dbReady.then(() => {
setInterval(cls.wrap(regularBackup), 4 * 60 * 60 * 1000);
setInterval(cls.wrap(regularBackup), 4 * 60 * 60 * 1000);
// kickoff first backup soon after start up
setTimeout(cls.wrap(regularBackup), 5 * 60 * 1000);
});
// kickoff first backup soon after start up
setTimeout(cls.wrap(regularBackup), 5 * 60 * 1000);
module.exports = {
backupNow,