mirror of
https://github.com/cryptpad/cryptpad.git
synced 2026-09-13 18:45:43 +05:00
Merge branch 'soon' into 5.3-storage
This commit is contained in:
commit
0bf26588e5
@ -779,12 +779,14 @@ var commands = {
|
||||
|
||||
// addFirstAdmin is an anon_rpc command
|
||||
Admin.addFirstAdmin = function (Env, data, cb) {
|
||||
if (!Env.installToken) { return void cb('EINVAL'); }
|
||||
var token = data.token;
|
||||
if (!token || !data.edPublic) { return void cb('MISSING_ARGS'); }
|
||||
if (token.length !== 64 || data.edPublic.length !== 44) { return void cb('INVALID_ARGS'); }
|
||||
if (token !== Env.installToken) { return void cb('FORBIDDEN'); }
|
||||
if (Array.isArray(Env.admins) && Env.admins.length) { return void cb('EEXISTS'); }
|
||||
|
||||
var key = data.edPublic;
|
||||
if (token.length !== 64 || data.edPublic.length !== 44) { return void cb('INVALID_ARGS'); }
|
||||
|
||||
adminDecree(Env, null, function (err) {
|
||||
if (err) { return void cb(err); }
|
||||
|
||||
@ -167,6 +167,7 @@ module.exports.create = function (config) {
|
||||
|
||||
limits: {},
|
||||
admins: [],
|
||||
installToken: undefined,
|
||||
WARN: function (e, output) { // TODO deprecate this
|
||||
if (!Env.Log) { return; }
|
||||
if (e && output) {
|
||||
|
||||
102
lib/eviction.js
102
lib/eviction.js
@ -3,6 +3,10 @@ var Bloom = require("@mcrowe/minibloom");
|
||||
var Util = require("../lib/common-util");
|
||||
var Pins = require("../lib/pins");
|
||||
var Keys = require("./keys");
|
||||
var Path = require('node:path');
|
||||
var config = require("./load-config");
|
||||
var Fs = require("node:fs");
|
||||
var Fse = require("fs-extra");
|
||||
|
||||
var getNewestTime = function (stats) {
|
||||
return stats[['atime', 'ctime', 'mtime'].reduce(function (a, b) {
|
||||
@ -70,6 +74,103 @@ var evictArchived = function (Env, cb) {
|
||||
blobs = Env.blobStore;
|
||||
};
|
||||
|
||||
var migrateBlobRoot = function (from, to) {
|
||||
// only migrate subpaths, leave everything else alone
|
||||
if (!Path.dirname(from).startsWith(Path.dirname(to))) { return; }
|
||||
|
||||
// expects a directory
|
||||
var recurse = function (relativePath) {
|
||||
var src = Path.join(from, relativePath);
|
||||
var children;
|
||||
try {
|
||||
children = Fs.readdirSync(src);
|
||||
} catch (err) {
|
||||
if (err.code === 'ENOENT') { return; }
|
||||
// if you can't read a directory's contents
|
||||
// then nothing else will work, so just abort
|
||||
Log.verbose("EVICT_ARCHIVED_NOT_DIRECTORY", {
|
||||
error: err,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
var dest;
|
||||
if (children.length === 0) {
|
||||
try {
|
||||
Fse.removeSync(src);
|
||||
} catch (err2) {
|
||||
Log.error('EVICT_ARCHIVED_EMPTY_DIR_REMOVAL', {
|
||||
error: err2,
|
||||
});
|
||||
// removal is non-essential, so we can continue
|
||||
}
|
||||
} else {
|
||||
// make an equivalent path in the target directory
|
||||
dest = Path.join(to, relativePath);
|
||||
|
||||
try {
|
||||
Fse.mkdirpSync(dest);
|
||||
} catch (err3) {
|
||||
Log.error("EVICT_ARCHIVED_BLOB_MIGRATION", {
|
||||
error: err3,
|
||||
});
|
||||
|
||||
// failure to create the host directory
|
||||
// will cause problems when we try to move
|
||||
// so bail out here
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
children.forEach(function (child) {
|
||||
var childSrcPath = Path.join(src, child);
|
||||
var stat = Fs.statSync(childSrcPath);
|
||||
if (stat.isDirectory()) {
|
||||
return void recurse(Path.join(relativePath, child));
|
||||
}
|
||||
|
||||
var childDestPath = Path.join(dest, child);
|
||||
|
||||
try {
|
||||
Log.verbose("EVICT_ARCHIVED_MOVE_FROM_DEPRECATED_PATH", {
|
||||
from: childSrcPath,
|
||||
to: childDestPath,
|
||||
});
|
||||
Fse.moveSync(childSrcPath, childDestPath, {
|
||||
overwrite: false,
|
||||
});
|
||||
} catch (err4) {
|
||||
Log.error('EVICT_ARCHIVED_MOVE_FAILURE', {
|
||||
error: err4,
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
recurse('');
|
||||
};
|
||||
|
||||
/* In CryptPad 5.2.0 we merged a patch which converted
|
||||
all of CryptPad's root filepaths to their absolute form,
|
||||
rather than the relative paths we'd been using until then.
|
||||
Unfortunately, we overlooked a case where two absolute
|
||||
paths were concatenated together, resulting in blobs being
|
||||
archived to an incorrect path.
|
||||
|
||||
This migration detects evidence of incorrect archivals
|
||||
and moves such archived files to their intended location
|
||||
before continuing with the normal eviction procedure.
|
||||
*/
|
||||
var migrateIncorrectBlobs = function () {
|
||||
var incorrectPaths = [
|
||||
Path.join(Env.paths.archive, config.blobPath),
|
||||
Path.join(Env.paths.archive, Path.resolve(config.blobPath))
|
||||
];
|
||||
var correctPath = Path.join(Env.paths.archive, 'blob');
|
||||
incorrectPaths.forEach(root => {
|
||||
migrateBlobRoot(root, correctPath);
|
||||
});
|
||||
};
|
||||
|
||||
var removeArchivedChannels = function (w) {
|
||||
// this block will iterate over archived channels and removes them
|
||||
// if they've been in cold storage for longer than your configured archive time
|
||||
@ -186,6 +287,7 @@ var evictArchived = function (Env, cb) {
|
||||
};
|
||||
|
||||
nThen(loadStorage)
|
||||
.nThen(migrateIncorrectBlobs)
|
||||
.nThen(removeArchivedChannels)
|
||||
.nThen(removeArchivedBlobProofs)
|
||||
.nThen(removeArchivedBlobs)
|
||||
|
||||
@ -74,7 +74,7 @@ Stats.instanceData = function (Env) {
|
||||
}
|
||||
|
||||
// Admins can opt-in to providing more detailed information about the extent of the instance's usage
|
||||
if (!Env.provideAggregateStatistics) {
|
||||
if (Env.provideAggregateStatistics) {
|
||||
// check how many instances provide stats before we put more work into it
|
||||
data.providesAggregateStatistics = true;
|
||||
}
|
||||
|
||||
@ -19,7 +19,11 @@ var isValidId = function (id) {
|
||||
// helpers
|
||||
|
||||
var prependArchive = function (Env, path) {
|
||||
return Path.join(Env.archivePath, path);
|
||||
// Env has an absolute path to the blob storage
|
||||
// we want the path to the blob relative to that
|
||||
var relativePathToBlob = Path.relative(Env.blobPath, path);
|
||||
// the new path structure is the same, but relative to the blob archive root
|
||||
return Path.join(Env.archivePath, 'blob', relativePathToBlob);
|
||||
};
|
||||
|
||||
// /blob/<safeKeyPrefix>/<safeKey>/<blobPrefix>/<blobId>
|
||||
@ -492,7 +496,7 @@ BlobStore.create = function (config, _cb) {
|
||||
if (e) { CB(e); }
|
||||
}));
|
||||
|
||||
Fse.mkdirp(Path.join(Env.archivePath, Env.blobPath), w(function (e) {
|
||||
Fse.mkdirp(Path.join(Env.archivePath, './blob'), w(function (e) {
|
||||
if (e) { CB(e); }
|
||||
}));
|
||||
}).nThen(function (w) {
|
||||
|
||||
@ -1,18 +1,12 @@
|
||||
var prompt = require('prompt-confirm');
|
||||
const p = new prompt('Are you sure? This will permanently delete all existing data on your instance.');
|
||||
|
||||
const nThen = require("nthen");
|
||||
const Fs = require("fs");
|
||||
const Path = require("path");
|
||||
|
||||
var config = require("../lib/load-config");
|
||||
var Hash = require('../www/common/common-hash');
|
||||
var Env = require("../lib/env").create(config);
|
||||
Env.Log = { error: console.log };
|
||||
|
||||
var keyOrDefaultString = function (key, def) {
|
||||
return Path.resolve(typeof(config[key]) === 'string'? config[key]: def);
|
||||
};
|
||||
var paths = Env.paths;
|
||||
p.ask(function (answer) {
|
||||
if (!answer) {
|
||||
@ -20,7 +14,6 @@ p.ask(function (answer) {
|
||||
return;
|
||||
}
|
||||
console.log('Deleting all data...');
|
||||
var n = nThen;
|
||||
Object.values(paths).forEach(function (path) {
|
||||
console.log(`Deleting ${path}`);
|
||||
Fs.rmSync(path, { recursive: true, force: true });
|
||||
|
||||
@ -2320,7 +2320,6 @@ define([
|
||||
localStorage.setItem(Constants.tokenKey, data[Constants.tokenKey]);
|
||||
}
|
||||
}
|
||||
|
||||
initFeedback(data.feedback);
|
||||
};
|
||||
|
||||
@ -2729,6 +2728,7 @@ define([
|
||||
if (data.error) { throw new Error(data.error); }
|
||||
if (data.state === 'ALREADY_INIT') {
|
||||
data = data.returned;
|
||||
initFeedback(data.feedback);
|
||||
}
|
||||
|
||||
if (data.loggedIn) {
|
||||
|
||||
@ -111,7 +111,7 @@ var init = function (client, cb) {
|
||||
if (data && data.state === "ALREADY_INIT") {
|
||||
debug('Store already exists!');
|
||||
self.store = data.returned;
|
||||
return void cb(data.returned);
|
||||
return void cb(data);
|
||||
}
|
||||
self.store = data;
|
||||
cb(data);
|
||||
|
||||
@ -148,7 +148,7 @@ define([
|
||||
// if metadata is too large, drop the thumbnail.
|
||||
if (plaintext.length > 65535) {
|
||||
var temp = JSON.parse(JSON.stringify(metadata));
|
||||
delete metadata.thumbnail;
|
||||
delete temp.thumbnail;
|
||||
plaintext = Nacl.util.decodeUTF8(JSON.stringify(temp));
|
||||
}
|
||||
|
||||
|
||||
@ -25,6 +25,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
.flatpickr-calendar.open {
|
||||
z-index: 100001 !important; // Alertify is 100000
|
||||
}
|
||||
|
||||
@palette0: @cp_kanban-color0; // Default bg color for header
|
||||
@form-colors: @cp_form-palette;
|
||||
.form-colors(@form-colors; @index) when (@index > 0){
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
// This file is used when a user tries to export the entire CryptDrive.
|
||||
// Pads from the code app will be exported using this format instead of plain text.
|
||||
define([
|
||||
'/bower_components/secure-fabric.js/dist/fabric.min.js',
|
||||
'/lib/fabric.min.js',
|
||||
], function () {
|
||||
var module = {};
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user