Archive and restore UI in the admin panel
parent
7b68a868ce
commit
bd4b44476d
|
@ -167,12 +167,19 @@ var archiveDocument = function (Env, Server, cb, data) {
|
|||
// Env.blobStore.archive.proof(userSafeKey, blobId, cb)
|
||||
};
|
||||
|
||||
var restoreArchivedDocument = function (Env, Server, cb) {
|
||||
// Env.msgStore.restoreArchivedChannel(channelName, cb)
|
||||
// Env.blobStore.restore.blob(blobId, cb)
|
||||
// Env.blobStore.restore.proof(userSafekey, blobId, cb)
|
||||
var restoreArchivedDocument = function (Env, Server, cb, data) {
|
||||
var id = Array.isArray(data) && data[1];
|
||||
if (typeof(id) !== 'string' || id.length < 32) { return void cb("EINVAL"); }
|
||||
|
||||
cb("NOT_IMPLEMENTED");
|
||||
switch (id.length) {
|
||||
case 32:
|
||||
return void Env.msgStore.restoreArchivedChannel(id, cb);
|
||||
case 48:
|
||||
// Env.blobStore.restore.proof(userSafekey, id, cb) // XXX ....
|
||||
return void Env.blobStore.restore.blob(id, cb);
|
||||
default:
|
||||
return void cb("INVALID_ID_LENGTH");
|
||||
}
|
||||
};
|
||||
|
||||
// CryptPad_AsyncStore.rpc.send('ADMIN', ['CLEAR_CACHED_CHANNEL_INDEX', documentID], console.log)
|
||||
|
|
|
@ -681,9 +681,9 @@ var unarchiveChannel = function (env, channelName, cb) {
|
|||
// restore the metadata log
|
||||
Fse.move(archiveMetadataPath, metadataPath, w(function (err) {
|
||||
// if there's nothing to move, you're done.
|
||||
if (err && err.code === 'ENOENT') {
|
||||
/*if (err && err.code === 'ENOENT') {
|
||||
return CB();
|
||||
}
|
||||
}*/ // XXX make sure removing this part won't break anything
|
||||
// call back with an error if something goes wrong
|
||||
if (err) {
|
||||
w.abort();
|
||||
|
|
|
@ -97,5 +97,15 @@
|
|||
color: @colortheme_logo-2;
|
||||
}
|
||||
}
|
||||
|
||||
input.cp-admin-inval {
|
||||
border-color: red !important;
|
||||
}
|
||||
.cp-admin-nopassword {
|
||||
.cp-admin-pw {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -43,6 +43,8 @@ define([
|
|||
'general': [
|
||||
'cp-admin-flush-cache',
|
||||
'cp-admin-update-limit',
|
||||
'cp-admin-archive',
|
||||
'cp-admin-unarchive',
|
||||
// 'cp-admin-registration',
|
||||
],
|
||||
'quota': [
|
||||
|
@ -107,6 +109,141 @@ define([
|
|||
});
|
||||
return $div;
|
||||
};
|
||||
Messages.admin_archiveTitle = "Archive documents"; // XXX
|
||||
Messages.admin_archiveHint = "Make a document unavailable without deleting it permanently. It will be placed in an 'archive' directory and deleted after a few days (configurable in the server configuration file)."; // XXX
|
||||
Messages.admin_archiveButton = "Archive";
|
||||
|
||||
Messages.admin_unarchiveTitle = "Restore archived documents"; // XXX
|
||||
Messages.admin_unarchiveHint = "Restore a document that has previously been archived";
|
||||
Messages.admin_unarchiveButton = "Restore";
|
||||
|
||||
Messages.admin_archiveInput = "Document URL";
|
||||
Messages.admin_archiveInput2 = "Document password";
|
||||
Messages.admin_archiveInval = "Invalid document";
|
||||
Messages.restoredFromServer = "Pad restored";
|
||||
|
||||
var archiveForm = function (archive, $div, $button) {
|
||||
var label = h('label', { for: 'cp-admin-archive' }, Messages.admin_archiveInput);
|
||||
var input = h('input#cp-admin-archive', {
|
||||
type: 'text'
|
||||
});
|
||||
|
||||
var label2 = h('label.cp-admin-pw', {
|
||||
for: 'cp-admin-archive-pw'
|
||||
}, Messages.admin_archiveInput2);
|
||||
var input2 = UI.passwordInput({
|
||||
id: 'cp-admin-archive-pw',
|
||||
placeholder: Messages.login_password
|
||||
});
|
||||
var $pw = $(input2);
|
||||
$pw.addClass('cp-admin-pw');
|
||||
var $pwInput = $pw.find('input');
|
||||
|
||||
|
||||
$button.before(h('div.cp-admin-setlimit-form', [
|
||||
label,
|
||||
input,
|
||||
label2,
|
||||
input2
|
||||
]));
|
||||
|
||||
$div.addClass('cp-admin-nopassword');
|
||||
|
||||
var parsed;
|
||||
var $input = $(input).on('keypress change paste', function () {
|
||||
setTimeout(function () {
|
||||
$input.removeClass('cp-admin-inval');
|
||||
var val = $input.val().trim();
|
||||
if (!val) {
|
||||
$div.toggleClass('cp-admin-nopassword', true);
|
||||
return;
|
||||
}
|
||||
|
||||
parsed = Hash.isValidHref(val);
|
||||
$pwInput.val('');
|
||||
|
||||
if (!parsed || !parsed.hashData) {
|
||||
$div.toggleClass('cp-admin-nopassword', true);
|
||||
return void $input.addClass('cp-admin-inval');
|
||||
}
|
||||
|
||||
var pw = parsed.hashData.version !== 3 && parsed.hashData.password;
|
||||
$div.toggleClass('cp-admin-nopassword', !pw);
|
||||
});
|
||||
});
|
||||
$pw.on('keypress change', function () {
|
||||
setTimeout(function () {
|
||||
$pw.toggleClass('cp-admin-inval', !$pwInput.val());
|
||||
});
|
||||
});
|
||||
|
||||
var clicked = false;
|
||||
$button.click(function () {
|
||||
if (!parsed || !parsed.hashData) {
|
||||
UI.warn(Messages.admin_archiveInval);
|
||||
return;
|
||||
}
|
||||
var pw = parsed.hashData.password ? $pwInput.val() : undefined;
|
||||
var channel;
|
||||
if (parsed.hashData.version === 3) {
|
||||
channel = parsed.hashData.channel;
|
||||
} else {
|
||||
var secret = Hash.getSecrets(parsed.type, parsed.hash, pw);
|
||||
channel = secret && secret.channel;
|
||||
}
|
||||
|
||||
if (!channel) {
|
||||
UI.warn(Messages.admin_archiveInval);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clicked) { return; }
|
||||
clicked = true;
|
||||
|
||||
nThen(function (waitFor) {
|
||||
if (!archive) { return; }
|
||||
common.getFileSize(channel, waitFor(function (err, size) {
|
||||
if (!err && size === 0) {
|
||||
clicked = false;
|
||||
waitFor.abort();
|
||||
return void UI.warn(Messages.admin_archiveInval);
|
||||
}
|
||||
}));
|
||||
}).nThen(function () {
|
||||
sFrameChan.query('Q_ADMIN_RPC', {
|
||||
cmd: archive ? 'ARCHIVE_DOCUMENT' : 'RESTORE_ARCHIVED_DOCUMENT',
|
||||
data: channel
|
||||
}, function (err, obj) {
|
||||
var e = err || (obj && obj.error);
|
||||
clicked = false;
|
||||
if (e) {
|
||||
UI.warn(Messages.error);
|
||||
console.error(e);
|
||||
return;
|
||||
}
|
||||
UI.log(archive ? Messages.deletedFromServer : Messages.restoredFromServer);
|
||||
$input.val('');
|
||||
$pwInput.val('');
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
create['archive'] = function () {
|
||||
var key = 'archive';
|
||||
var $div = makeBlock(key, true);
|
||||
var $button = $div.find('button');
|
||||
archiveForm(true, $div, $button);
|
||||
return $div;
|
||||
};
|
||||
create['unarchive'] = function () {
|
||||
var key = 'unarchive';
|
||||
var $div = makeBlock(key, true);
|
||||
var $button = $div.find('button');
|
||||
archiveForm(false, $div, $button);
|
||||
return $div;
|
||||
};
|
||||
|
||||
create['registration'] = function () {
|
||||
var key = 'registration';
|
||||
var $div = makeBlock(key, true);
|
||||
|
|
|
@ -464,6 +464,8 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
|
|||
};
|
||||
|
||||
if (!/^https*:\/\//.test(href)) {
|
||||
// If it doesn't start with http(s), it should be a relative href
|
||||
if (!/^\//.test(href)) { return ret; }
|
||||
idx = href.indexOf('/#');
|
||||
ret.type = href.slice(1, idx);
|
||||
if (idx === -1) { return ret; }
|
||||
|
@ -661,7 +663,7 @@ Version 4: Data URL when not a realtime link yet (new pad or "static" app)
|
|||
if (parsed.hashData.key && !/^[a-zA-Z0-9+-/=]+$/.test(parsed.hashData.key)) { return; }
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return parsed;
|
||||
};
|
||||
|
||||
Hash.decodeDataOptions = function (opts) {
|
||||
|
|
Loading…
Reference in New Issue