New support: disable quota for the support pin log

This commit is contained in:
yflory 2024-02-22 15:48:34 +01:00
parent 643e859e7c
commit a67b1ea7cc
11 changed files with 72 additions and 49 deletions

View file

@ -9,7 +9,7 @@ const Pinning = module.exports;
const Util = require("../common-util");
const nThen = require("nthen");
//const escapeKeyCharacters = Util.escapeKeyCharacters;
const escapeKeyCharacters = Util.escapeKeyCharacters;
const unescapeKeyCharacters = Util.unescapeKeyCharacters;
var sumChannelSizes = function (sizes) { // FIXME this synchronous code could be done by a worker
@ -174,6 +174,23 @@ Pinning.pinChannel = function (Env, safeKey, channels, cb) {
return void cb();
}
let pin = function () {
Env.pinStore.message(safeKey, JSON.stringify(['PIN', toStore, +new Date()]),
function (e) {
if (e) { return void cb(e); }
if (!session || !session.channels) { return void cb(); }
toStore.forEach(function (channel) {
session.channels[channel] = true;
});
cb();
});
};
// Support tickets are always pinned, no need to check the limit
if (safeKey === escapeKeyCharacters(Env.supportPinKey)) {
return void pin();
}
getMultipleFileSize(Env, toStore, function (e, sizes) {
if (typeof(sizes) === 'undefined') { return void cb(e); }
var pinSize = sumChannelSizes(sizes); // FIXME don't do this in the main thread...
@ -185,15 +202,7 @@ Pinning.pinChannel = function (Env, safeKey, channels, cb) {
}
if (pinSize > free) { return void cb('E_OVER_LIMIT'); }
Env.pinStore.message(safeKey, JSON.stringify(['PIN', toStore, +new Date()]),
function (e) {
if (e) { return void cb(e); }
if (!session || !session.channels) { return; }
toStore.forEach(function (channel) {
session.channels[channel] = true;
});
cb();
});
pin();
});
});
});
@ -238,7 +247,26 @@ Pinning.resetUserPins = function (Env, safeKey, channelList, _cb) {
return void cb();
}
let reset = function () {
var pins = {};
Env.pinStore.message(safeKey, JSON.stringify(['RESET', channelList, +new Date()]),
function (e) {
if (e) { return void cb(e); }
channelList.forEach(function (channel) {
pins[channel] = true;
});
// update in-memory cache IFF the reset was allowed.
if (session) { session.channels = pins; }
cb();
});
};
// Support tickets are always pinned, no need to check the limit
if (safeKey === escapeKeyCharacters(Env.supportPinKey)) {
return void reset();
}
getMultipleFileSize(Env, channelList, function (e, sizes) {
if (typeof(sizes) === 'undefined') { return void cb(e); }
var pinSize = sumChannelSizes(sizes);
@ -259,24 +287,7 @@ Pinning.resetUserPins = function (Env, safeKey, channelList, _cb) {
They will not be able to pin additional pads until they upgrade
or delete enough files to go back under their limit. */
if (pinSize > limit[0] && session.hasPinned) { return void(cb('E_OVER_LIMIT')); }
Env.pinStore.message(safeKey, JSON.stringify(['RESET', channelList, +new Date()]),
function (e) {
if (e) { return void cb(e); }
channelList.forEach(function (channel) {
pins[channel] = true;
});
var oldChannels;
if (session.channels && typeof(session.channels) === 'object') {
oldChannels = Object.keys(session.channels);
} else {
oldChannels = [];
}
// update in-memory cache IFF the reset was allowed.
session.channels = pins;
cb();
});
reset();
});
});
};

View file

@ -210,10 +210,20 @@ commands.SET_ADMIN_EMAIL = makeGenericSetter('adminEmail', args_isString);
commands.SET_SUPPORT_MAILBOX = makeGenericSetter('supportMailbox', function (args) {
return args_isString(args) && Core.isValidPublicKey(args[0]);
});
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_SUPPORT_MAILBOX2', ["Tdz6+fE9N9XXBY93rW5qeNa/k27yd40c0vq7EJyt7jA="]]], console.log)
commands.SET_SUPPORT_MAILBOX2 = makeGenericSetter('newSupportMailbox', function (args) {
return args_isString(args) && (Core.isValidPublicKey(args[0]) || !args[0]);
});
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_SUPPORT_KEYS', ["Tdz6+fE9N9XXBY93rW5qeNa/k27yd40c0vq7EJyt7jA=", "Tdz6+fE9N9XXBY93rW5qeNa/k27yd40c0vq7EJyt7jA="]]], console.log)
commands.SET_SUPPORT_KEYS = function (Env, args) {
const curvePublic = args[0]; // Support mailbox key
const edPublic = args[1]; // Support pin log
let validated = typeof(curvePublic) === "string" &&
(Core.isValidPublicKey(curvePublic) || !curvePublic) &&
typeof(edPublic) === "string" &&
(Core.isValidPublicKey(edPublic) || !edPublic);
if (!validated) { throw new Error('INVALID_ARGS'); }
if (Env.supportMailboxKey === curvePublic && Env.supportPinKey === edPublic) { return false; }
Env.supportMailboxKey = curvePublic;
Env.supportPinKey = edPublic;
return true;
};
// CryptPad_AsyncStore.rpc.send('ADMIN', [ 'ADMIN_DECREE', ['SET_INSTANCE_PURPOSE', ["development"]]], console.log)
commands.SET_INSTANCE_PURPOSE = makeGenericSetter('instancePurpose', args_isString);

View file

@ -147,7 +147,7 @@ module.exports.create = function (config) {
adminEmail: config.adminEmail,
supportMailbox: config.supportMailboxPublicKey,
newSupportMailbox: undefined,
supportMailboxKey: undefined,
metadata_cache: {},
channel_cache: {},

View file

@ -571,7 +571,7 @@ var serveConfig = makeRouteCache(function () {
adminKeys: Env.admins,
inactiveTime: Env.inactiveTime,
supportMailbox: Env.supportMailbox,
newSupportMailbox: Env.newSupportMailbox,
supportMailboxKey: Env.supportMailboxKey,
defaultStorageLimit: Env.defaultStorageLimit,
maxUploadSize: Env.maxUploadSize,
premiumUploadSize: Env.premiumUploadSize,

View file

@ -45,7 +45,7 @@ Stats.instanceData = function (Env) {
// we expect that you enable your support mailbox
data.supportMailbox = Boolean(Env.supportMailbox);
data.newSupportMailbox = Boolean(Env.newSupportMailbox);
data.supportMailboxKey = Boolean(Env.supportMailboxKey);
// do you allow registration?
data.restrictRegistration = Boolean(Env.restrictRegistration);

View file

@ -2926,7 +2926,7 @@ Example
Messages.admin_supportNewConfirm = "Are you sure? This will remove access to all current moderators.";
create['support-new'] = function () {
var $div = makeBlock('support-new'); // Msg.admin_supportNewHint, .admin_supportNewTitle
var newSupportKey = ApiConfig.newSupportMailbox;
var newSupportKey = ApiConfig.supportMailboxKey;
(function () {
var state = h('div');
var $state = $(state).appendTo($div);
@ -2989,6 +2989,8 @@ Example
var keyPair = Nacl.box.keyPair();
var pub = Nacl.util.encodeBase64(keyPair.publicKey);
var priv = Nacl.util.encodeBase64(keyPair.secretKey);
var ed = Nacl.sign.keyPair.fromSeed(keypair.secretKey);
var edPub = Nacl.util.encodeBase64(ed.publicKey);
// Store the private key first. It won't be used until the decree is accepted.
sFrameChan.query("Q_ADMIN_MAILBOX", {
version: 2,
@ -3003,7 +3005,7 @@ Example
// Then send the decree
sFrameChan.query('Q_ADMIN_RPC', {
cmd: 'ADMIN_DECREE',
data: ['SET_SUPPORT_MAILBOX2', [pub]]
data: ['SET_SUPPORT_MAILBOX2', [pub, edPub]]
}, function (e, response) {
$button.removeAttr('disabled');
if (e || response.error) {

View file

@ -1623,7 +1623,7 @@ define([
if (!priv || !pub) { return void cb({error: 'EINVAL'}); }
var channel = Hash.getChannelIdFromKey(pub);
var mailboxes = store.proxy.mailboxes = store.proxy.mailboxes || {};
var key = isNewSupport ? 'support2' : 'supportadmin';
var key = isNewSupport ? 'supportteam' : 'supportadmin';
var box = mailboxes[key] = {
channel: channel,
viewed: [],

View file

@ -20,7 +20,7 @@ define([
'notifications',
'supportadmin',
'support',
'support2',
'supportteam',
'broadcast'
];
var BLOCKING_TYPES = [

View file

@ -24,12 +24,12 @@ define([
require(['/api/config?' + (+new Date())], function (NewConfig) {
ctx.adminKeys = NewConfig.adminKeys; // Update admin keys // XXX MODERATOR
var supportKey = NewConfig.newSupportMailbox;
var supportKey = NewConfig.supportMailboxKey;
if (!supportKey) { return void cb('E_NOT_INIT'); }
// If admin, check key
if (isAdmin && Util.find(ctx.store.proxy, [
'mailboxes', 'support2', 'keys', 'curvePublic']) !== supportKey) {
'mailboxes', 'supportteam', 'keys', 'curvePublic']) !== supportKey) {
return void cb('EFORBIDDEN');
}
@ -37,7 +37,7 @@ define([
return ctx.adminRdyEvt.reg(() => {
cb(null, {
myCurve: data.adminCurvePrivate || Util.find(ctx.store.proxy, [
'mailboxes', 'support2', 'keys', 'curvePrivate']),
'mailboxes', 'supportteam', 'keys', 'curvePrivate']),
theirPublic: data.curvePublic,
notifKey: data.curvePublic
});
@ -461,7 +461,7 @@ define([
let cb = Util.mkAsync(_cb);
let Nacl = Crypto.Nacl;
let proxy = ctx.store.proxy;
let curvePrivate = Util.find(proxy, ['mailboxes', 'support2', 'keys', 'curvePrivate']);
let curvePrivate = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
if (!curvePrivate) { return void cb('EFORBIDDEN'); }
let edPrivate, edPublic
try {
@ -526,8 +526,8 @@ define([
var initializeSupportAdmin = function (ctx, waitFor) {
let unlock = waitFor();
let proxy = ctx.store.proxy;
let supportKey = Util.find(proxy, ['mailboxes', 'support2', 'keys', 'curvePublic']);
let privateKey = Util.find(proxy, ['mailboxes', 'support2', 'keys', 'curvePrivate']);
let supportKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
let privateKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
ctx.adminRdyEvt = Util.mkEvent(true);
nThen((waitFor) => {
getKeys(ctx, false, {}, waitFor((err, obj) => {
@ -580,7 +580,7 @@ define([
clients: {}
};
if (Util.find(store, ['proxy', 'mailboxes', 'support2'])) {
if (Util.find(store, ['proxy', 'mailboxes', 'supportteam'])) {
initializeSupportAdmin(ctx, waitFor);
}

View file

@ -163,7 +163,7 @@ define([
// Call the onMessage handlers
var isNotification = function (type) {
return type === "notifications" || /^team-/.test(type) || type === "broadcast" || type === "reminders" || type === "support2";
return type === "notifications" || /^team-/.test(type) || type === "broadcast" || type === "reminders" || type === "supportteam";
};
var pushMessage = function (data, handler) {
var todo = function (f) {

View file

@ -1173,7 +1173,7 @@ MessengerUI, Messages, Pages) {
$button.addClass('fa-bell');
};
Common.mailbox.subscribe(['notifications', 'team', 'broadcast', 'reminders', 'support2'], {
Common.mailbox.subscribe(['notifications', 'team', 'broadcast', 'reminders', 'supportteam'], {
onMessage: function (data, el) {
if (toolbar.$top.hasClass('toolbar-hidden')) {
$('.cp-collapsed-notif').css('display', '');