Merge pull request #1973 from cryptpad/moderation

Moderation
This commit is contained in:
yflory 2025-06-27 16:03:41 +02:00 committed by GitHub
commit 40e26032d5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 98 additions and 5 deletions

View File

@ -134,8 +134,9 @@ define(req, function(AppConfig, Default, Language) {
}
};
Messages.admin_documentsDeletionHint = "Archive a list of documents using their id (one document id per line)";
Messages.admin_documentsDeletionTitle = "Archive multiple documents";
Messages.help_close_button = 'Close help notification'; // XXX
// XXX
Messages.badges_admin = "Instance administrator";
Messages.badges_moderator = "Instance moderator";
Messages.badges_premium = "Premium user";

View File

@ -172,7 +172,8 @@ var flushCache = function (Env, Server, cb) {
};
// CryptPad_AsyncStore.rpc.send('ADMIN', ['ARCHIVE_DOCUMENT', documentID], console.log)
var archiveDocument = function (Env, Server, cb, data) {
var archiveDocument = function (Env, Server, _cb, data) {
const cb = Util.mkAsync(_cb);
if (!Array.isArray(data)) { return void cb("EINVAL"); }
var args = data[1];
@ -221,6 +222,28 @@ var archiveDocument = function (Env, Server, cb, data) {
// Env.blobStore.archive.proof(userSafeKey, blobId, cb)
};
// CryptPad_AsyncStore.rpc.send('ADMIN', ['ARCHIVE_DOCUMENTS', documents], console.log)
var archiveDocuments = function (Env, Server, cb, data) {
if (!Array.isArray(data)) { return void cb("EINVAL"); }
let args = data[1];
const { list, reason } = args;
if (!Array.isArray(list)) { return void cb('EINVAL'); }
let n = nThen;
let failed = [];
list.forEach(id => {
n = n((w) => {
archiveDocument(Env, Server, w(err => {
console.log(err);
if (err && err !== 'ENOENT') { failed.push(id); }
}), [0, { id, reason }]);
}).nThen;
});
n(() => {
cb(void 0, { state: true, failed });
});
};
var removeDocument = function (Env, Server, cb, data) {
if (!Array.isArray(data)) { return void cb("EINVAL"); }
var args = data[1];
@ -1088,6 +1111,7 @@ var commands = {
RESTORE_ARCHIVED_BLOCK: restoreArchivedBlock,
ARCHIVE_DOCUMENT: archiveDocument,
ARCHIVE_DOCUMENTS: archiveDocuments,
RESTORE_ARCHIVED_DOCUMENT: restoreArchivedDocument,
ARCHIVE_ACCOUNT: archiveAccount,

View File

@ -127,9 +127,9 @@ define([
content : [
'account-metadata',
'document-metadata',
'documents-deletion',
'block-metadata',
'totp-recovery',
]
},
'support' : { // Msg.admin_cat_support
@ -2390,6 +2390,48 @@ define([
return tableObj.table;
};
// Msg.admin_documentsDeletionHint.admin_documentsDeletionTitle
sidebar.addItem('documents-deletion', cb => {
const textarea = blocks.textarea({
'aria-labelledby': 'cp-admin-documents-deletion'
});
const $textarea = $(textarea);
const archiveButton = blocks.activeButton('danger', '',
Messages.admin_archiveButton, () => {
const $btn = $(archiveButton);
justifyArchivalDialog('', result => {
const val = $textarea.val().trim();
const all = val.split('\n').filter(str => {
let type = DOCUMENT_TYPES[str.length];
return ['channel', 'file'].includes(type);
});
console.error(val);
console.error(result);
disable($btn);
sframeCommand('ARCHIVE_DOCUMENTS', {
list: all,
reason: result,
}, (err, arr) => {
const res = Array.isArray(arr) && arr[0];
enable($btn);
if (err) {
console.error(err);
return void UI.warn(Messages.error);
}
if (Array.isArray(res?.failed)
&& res?.failed.length) {
console.error("Failed deletion:");
console.error(res?.failed);
}
$textarea.val('');
UI.log(Messages.archivedFromServer);
});
});
}, true);
const nav = blocks.nav([archiveButton]);
const div = blocks.form([textarea], nav);
cb(div);
});
// Msg.admin_documentMetadataHint.admin_documentMetadataTitle
sidebar.addItem('document-metadata', function(cb){

View File

@ -14,6 +14,7 @@ define([
'/common/common-hash.js',
'/common/common-constants.js',
'/common/hyperscript.js',
'/common/clipboard.js',
'/api/config',
'/common/common-realtime.js',
'/customize/messages.js',
@ -36,6 +37,7 @@ define([
Hash,
Constants,
h,
Clipboard,
ApiConfig,
CommonRealtime,
Messages,
@ -707,15 +709,39 @@ define([
toolbar.$drawer.append($histEntry);
var $content = common.createButton(null, true, {
icon: 'fa-question',
icon: 'fa-clock-o',
title: 'Get debugging graph', // TODO
name: 'graph',
text: 'Replay',
id: 'cp-app-debug-get-content'
});
$content.click(getContent);
var $contentEntry = UIElements.getEntryFromButton($content);
console.error($contentEntry);
toolbar.$drawer.append($contentEntry);
var priv = metadataMgr.getPrivateData();
if (priv.debugDrive) {
var $drive = common.createButton(null, true, {
icon: 'fa-hdd-o',
title: 'Get Shared Folder content', // TODO
text: 'SF channel list',
id: 'cp-app-debug-get-channels'
});
$drive.click(() => {
let p = JSON.parse(info.realtime.getUserDoc());
const fd = p?.drive?.filesData || p?.filesData;
let all = Object.keys(fd).map(id => {
return fd[id]?.channel;
});
console.error(all);
Clipboard.copy(all.join('\n'), (err) => {
if (err) { return UI.warn(Messages.error); }
UI.log(Messages.genericCopySuccess);
});
});
var $driveEntry = UIElements.getEntryFromButton($drive);
toolbar.$drawer.append($driveEntry);
}
};
config.onReady = function (info) {