New support: lint compliance and clean XXX

This commit is contained in:
yflory 2024-02-27 17:17:45 +01:00
parent a62dc7cfae
commit d525852a8f
10 changed files with 159 additions and 209 deletions

View file

@ -942,16 +942,13 @@ var removeModerator = (Env, Server, cb, data) => {
const id = Array.isArray(data) && data[1];
Moderators.delete(Env, id, cb);
};
var archiveSupport = (Env, Server, cb, data) => {
var archiveSupport = (Env, Server, cb) => {
let supportPinKey = Env.supportPinKey;
console.log(supportPinKey);
getPinList(Env, Server, (err, list) => {
console.log(list);
if (err) { return void cb(err); }
let n = nThen;
list.forEach(id => {
n = n(waitFor => {
console.log(id);
archiveDocument(Env, Server, waitFor(), [null, {id, reason:'DISABLE_SUPPORT'}]);
}).nThen;
});

View file

@ -389,7 +389,7 @@ commands.SET_BEARER_SECRET = function (Env, args) {
};
// [<command>, <args>, <author>, <time>]
var handleCommand = Decrees.handleCommand = function (Env, line, cb) {
var handleCommand = Decrees.handleCommand = function (Env, line) {
var command = line[0];
var args = line[1];

View file

@ -45,7 +45,7 @@ Basic.readDir = function (Env, path, cb) {
if (!path) { return void pathError(cb); }
Fs.readdir(path, cb);
};
Basic.readDirSync = function (Env, path, cb) {
Basic.readDirSync = function (Env, path) {
if (!path) { return []; }
return Fs.readdirSync(path);
};

View file

@ -2932,7 +2932,7 @@ Example
let supportKey = ApiConfig.supportMailboxKey;
let edPublic = common.getMetadataMgr().getPrivateData().edPublic; // My edPublic
let refresh = function () {};
const redraw = function (moderatorsData, oldPrivKey) {
const redraw = function (moderatorsData) {
$div.empty();
const state = h('div');
@ -2988,21 +2988,6 @@ Example
});
});
/*
const getEncryptor = (curvePrivate) => {
const seed = curvePrivate.slice(0,24);
const hash = Hash.getEditHashFromKeys({
version: 2,
type: 'support',
keys: {
editKeyStr: seed
}
});
const secret = Hash.getSecrets('support', hash);
return Crypto.createEncryptor(secret.keys);
};
console.log(oldPrivKey, getEncryptor(oldPrivKey));
*/
const getContactData = (curve) => {
let friends = common.getFriends(true);
let f = friends[curve || 'me'];
@ -3029,9 +3014,6 @@ Example
UI.warn(Messages.error);
};
//const oldCrypto = supportKey ? getEncryptor(oldPrivKey) : undefined;
//const newCrypto = getEncryptor(priv);
nThen((waitFor) => {
// Add myself to moderator role if not already there
let me = getContactData();
@ -3073,10 +3055,7 @@ Example
}
// User added to support team in database, send them the keys
APP.supportModule.execCommand('ADD_MODERATOR', userData, (obj) => {
// XXX IF ERROR, (can't notify) remove from DB?
cb();
});
APP.supportModule.execCommand('ADD_MODERATOR', userData, cb);
});
};
const removeModerator = (ed) => {
@ -3093,20 +3072,13 @@ Example
};
Util.onClickEnter($button, function () {
/*
if (supportKey) {
return void UI.confirm(Messages.admin_supportNewConfirm, function (yes) {
if (yes) { generateKey(); }
});
}
*/
generateKey();
});
const drawModerators = () => {
if (!supportKey) { return; }
const members = {};
const friends = Util.clone(common.getFriends(false))
const friends = Util.clone(common.getFriends(false));
Object.keys(moderatorsData).forEach((ed) => {
let m = moderatorsData[ed];
members[m.curvePublic] = {
@ -3170,10 +3142,9 @@ Example
drawModerators();
};
refresh = () => {
let oldKey, moderators;
let moderators;
nThen((waitFor) => {
APP.supportModule.execCommand('GET_PRIVATE_KEY', {}, waitFor((obj) => {
oldKey = obj && obj.curvePrivate;
supportKey = obj && obj.curvePublic;
}));
}).nThen((waitFor) => {
@ -3189,7 +3160,7 @@ Example
moderators = response[0];
}));
}).nThen(() => {
redraw(moderators, oldKey);
redraw(moderators);
});
};
refresh();

View file

@ -2236,7 +2236,7 @@ define([
};
var $userAdmin = UIElements.createDropdown(dropdownConfigUser);
var $survey = $userAdmin.find('.cp-toolbar-survey').parent();;
var $survey = $userAdmin.find('.cp-toolbar-survey').parent();
var $surveyHr = $survey.next('[role="separator"]');
if (!surveyURL) {
$survey.hide();

View file

@ -887,7 +887,6 @@ define([
// Update ChainPad doc
support.updateAdminTicket(content);
// XXX TODO opt out
if (Util.find(ctx.store.proxy, ['settings', 'general', 'disableSupportNotif'])) {
return void cb(true);
}
@ -912,7 +911,6 @@ define([
handlers['ADD_MODERATOR'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
var newKey = content.supportKey;
var support = Util.find(ctx, ['store', 'modules', 'support']);
support.updateAdminKey(content, cb);
@ -920,7 +918,6 @@ define([
handlers['MODERATOR_NEW_KEY'] = function (ctx, box, data, cb) {
var msg = data.msg;
var content = msg.content;
var newKey = content.supportKey;
var support = Util.find(ctx, ['store', 'modules', 'support']);
support.updateAdminKey(content, function () {

View file

@ -70,7 +70,7 @@ define([
theirPublic = obj.theirPublic;
myCurve = obj.myCurve;
}));
}).nThen((waitFor) => {
}).nThen(() => {
var keys = Crypto.Curve.deriveKeys(theirPublic, myCurve);
var crypto = Crypto.Curve.createEncryptor(keys);
var cfg = {
@ -102,6 +102,7 @@ define([
cfg.onChannelError = cb;
cfg.onReady = function () {
cb(null, all);
close();
};
cpNf = CpNetflux.start(cfg);
});
@ -237,6 +238,123 @@ define([
});
};
// INITIALIZE ADMIN
var getPinList = function (ctx) {
if (!ctx.adminDoc || !ctx.supportRpc) { return; }
let adminChan = ctx.adminDoc.metadata && ctx.adminDoc.metadata.channel;
let doc = ctx.adminDoc.proxy;
let t = doc.tickets;
let list = [
adminChan,
...Object.keys(t.active),
...Object.keys(t.pending),
...Object.keys(t.closed)
];
return Util.deduplicateString(list).sort();
};
var initAdminRpc = function (ctx, _cb) {
let cb = Util.mkAsync(_cb);
let proxy = ctx.store.proxy;
let curvePrivate = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
if (!curvePrivate) { return void cb('EFORBIDDEN'); }
let edPrivate, edPublic;
try {
let pair = Nacl.sign.keyPair.fromSeed(Nacl.util.decodeBase64(curvePrivate));
edPrivate = Nacl.util.encodeBase64(pair.secretKey);
edPublic = Nacl.util.encodeBase64(pair.publicKey);
} catch (e) {
return void cb(e);
}
Pinpad.create(ctx.store.network, {
edPublic: edPublic,
edPrivate: edPrivate
}, (e, call) => {
if (e) { return void cb(e); }
console.log("Support RPC ready, public key is ", edPublic);
ctx.supportRpc = call;
cb();
});
};
var loadAdminDoc = function (ctx, hash, cb) {
var secret = Hash.getSecrets('support', hash);
var listmapConfig = {
data: {},
channel: secret.channel,
crypto: Crypto.createEncryptor(secret.keys),
userName: 'support',
ChainPad: ChainPad,
classic: true,
network: ctx.store.network,
metadata: {
validateKey: secret.keys.validateKey || undefined,
},
};
var rt = ctx.adminDoc = Listmap.create(listmapConfig);
rt.proxy.on('ready', function () {
var doc = rt.proxy;
doc.tickets = doc.tickets || {};
doc.tickets.active = doc.tickets.active || {};
doc.tickets.closed = doc.tickets.closed || {};
doc.tickets.pending = doc.tickets.pending || {};
ctx.adminRdyEvt.fire();
cb();
if (!ctx.supportRpc) { return; }
// Check pin list
let list = getPinList(ctx);
let local = Hash.hashChannelList(list);
ctx.supportRpc.getServerHash(function (e, hash) {
if (e) { return void console.warn(e); }
if (hash !== local) {
ctx.supportRpc.reset(list, function (e) {
if (e) { console.warn(e); }
});
}
});
});
};
var initializeSupportAdmin = function (ctx, isReset, waitFor) {
let unlock = waitFor();
let proxy = ctx.store.proxy;
let supportKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
let privateKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
if (!isReset) { ctx.adminRdyEvt = Util.mkEvent(true); }
nThen((waitFor) => {
getKeys(ctx, false, {}, waitFor((err, obj) => {
setTimeout(unlock); // Unlock loading process
if (err) { return void waitFor.abort(); }
if (obj.theirPublic !== supportKey) {
try {
delete proxy.mailboxes.supportteam;
ctx.store.mailbox.close('supportteam');
} catch (e) {}
delete ctx.adminRdyEvt;
return void waitFor.abort();
}
}));
}).nThen((waitFor) => {
initAdminRpc(ctx, waitFor((err) => {
if (err) { console.error('Support RPC not ready', err); }
}));
}).nThen((waitFor) => {
let seed = privateKey.slice(0,24); // XXX better way to get seed? also in admin/inner.js
let hash = Hash.getEditHashFromKeys({
version: 2,
type: 'support',
keys: {
editKeyStr: seed
}
});
loadAdminDoc(ctx, hash, waitFor());
}).nThen(() => {
console.log('Support admin loaded');
});
};
// USER COMMANDS
var getMyTickets = function (ctx, data, cId, cb) {
@ -305,7 +423,7 @@ define([
cb({deleted: true});
};
// ADMIN COMMANDS
// MODERATOR COMMANDS
var listTicketsAdmin = function (ctx, data, cId, cb) {
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
@ -353,7 +471,7 @@ define([
entry.premium = premium;
if (senderKey) {
entry.lastAdmin = ctx.moderatorKeys.indexOf(senderKey) !== -1
entry.lastAdmin = ctx.moderatorKeys.indexOf(senderKey) !== -1;
}
}
cb(res);
@ -404,6 +522,7 @@ define([
});
});
};
// Mailbox events
var notifyClient = function (ctx, admin, type, channel) {
@ -416,7 +535,7 @@ define([
var addAdminTicket = function (ctx, data, cb) {
// Wait for the chainpad to be ready before adding the data
if (!ctx.adminRdyEvt) { return void cb(true); } // XXX not an admin, delete mailbox?
if (!ctx.adminRdyEvt) { return void cb(true); }
ctx.adminRdyEvt.reg(() => {
let supportKey;
@ -452,13 +571,13 @@ define([
});
notifyClient(ctx, true, 'NEW_TICKET', data.channel);
if (ctx.supportRpc) { ctx.supportRpc.pin([data.channel], () => {}); }
});
}, rdmTo);
});
});
};
var updateAdminTicket = function (ctx, data) {
// Wait for the chainpad to be ready before adding the data
if (!ctx.adminRdyEvt) { return; } // XXX not an admin, delete mailbox?
if (!ctx.adminRdyEvt) { return; }
ctx.adminRdyEvt.reg(() => {
// random timeout to avoid duplication wiht multiple admins
@ -478,11 +597,11 @@ define([
t.time = data.time;
t.lastAdmin = false;
notifyClient(ctx, true, 'UPDATE_TICKET', data.channel);
});
}, rdmTo);
});
};
var checkAdminTicket = function (ctx, data, cb) {
if (!ctx.adminRdyEvt) { return void cb(false); } // XXX not an admin, delete mailbox?
if (!ctx.adminRdyEvt) { return void cb(true); }
ctx.adminRdyEvt.reg(() => {
let doc = ctx.adminDoc.proxy;
@ -541,128 +660,11 @@ define([
});
};
// INITIALIZE ADMIN
var getPinList = function (ctx) {
if (!ctx.adminDoc || !ctx.supportRpc) { return; }
let adminChan = ctx.adminDoc.metadata && ctx.adminDoc.metadata.channel;
let doc = ctx.adminDoc.proxy;
let t = doc.tickets;
let list = [
adminChan,
...Object.keys(t.active),
...Object.keys(t.pending),
...Object.keys(t.closed)
];
return Util.deduplicateString(list).sort();
};
var initAdminRpc = function (ctx, _cb) {
let cb = Util.mkAsync(_cb);
let proxy = ctx.store.proxy;
let curvePrivate = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
if (!curvePrivate) { return void cb('EFORBIDDEN'); }
let edPrivate, edPublic
try {
let pair = Nacl.sign.keyPair.fromSeed(Nacl.util.decodeBase64(curvePrivate));
edPrivate = Nacl.util.encodeBase64(pair.secretKey);
edPublic = Nacl.util.encodeBase64(pair.publicKey);
} catch (e) {
return void cb(e);
}
Pinpad.create(ctx.store.network, {
edPublic: edPublic,
edPrivate: edPrivate
}, (e, call) => {
if (e) { return void cb(e); }
console.log("Support RPC ready, public key is ", edPublic);
ctx.supportRpc = call;
cb();
});
};
var loadAdminDoc = function (ctx, hash, cb) {
var secret = Hash.getSecrets('support', hash);
var listmapConfig = {
data: {},
channel: secret.channel,
crypto: Crypto.createEncryptor(secret.keys),
userName: 'support',
ChainPad: ChainPad,
classic: true,
network: ctx.store.network,
//Cache: Cache, // XXX XXX XXX
metadata: {
validateKey: secret.keys.validateKey || undefined,
},
};
var rt = ctx.adminDoc = Listmap.create(listmapConfig);
// XXX on change, tell current user that support has changed?
rt.proxy.on('ready', function () {
var doc = rt.proxy;
doc.tickets = doc.tickets || {};
doc.tickets.active = doc.tickets.active || {};
doc.tickets.closed = doc.tickets.closed || {};
doc.tickets.pending = doc.tickets.pending || {};
ctx.adminRdyEvt.fire();
cb();
if (!ctx.supportRpc) { return; }
// Check pin list
let list = getPinList(ctx);
let local = Hash.hashChannelList(list);
ctx.supportRpc.getServerHash(function (e, hash) {
if (e) { return void console.warn(e); }
if (hash !== local) {
ctx.supportRpc.reset(list, function (e, hash) {
if (e) { console.warn(e); }
});
}
});
});
};
var initializeSupportAdmin = function (ctx, isReset, waitFor) {
let unlock = waitFor();
let proxy = ctx.store.proxy;
let supportKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
let privateKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
if (!isReset) { ctx.adminRdyEvt = Util.mkEvent(true); }
nThen((waitFor) => {
getKeys(ctx, false, {}, waitFor((err, obj) => {
setTimeout(unlock); // Unlock loading process
if (err) { return void waitFor.abort(); }
if (obj.theirPublic !== supportKey) {
try {
delete proxy.mailboxes.supportteam;
ctx.store.mailbox.close('supportteam');
} catch (e) {}
delete ctx.adminRdyEvt;
return void waitFor.abort();
}
}));
}).nThen((waitFor) => {
initAdminRpc(ctx, waitFor((err) => {
if (err) { console.error('Support RPC not ready', err); }
}));
}).nThen((waitFor) => {
let seed = privateKey.slice(0,24); // XXX better way to get seed? also in admin/inner.js
let hash = Hash.getEditHashFromKeys({
version: 2,
type: 'support',
keys: {
editKeyStr: seed
}
});
console.error(hash);
loadAdminDoc(ctx, hash, waitFor());
}).nThen(() => {
console.log('Support admin loaded')
});
};
// ADMIN COMMANDS
let updateServerKey = (ctx, curvePublic, curvePrivate, cb) => {
let edPrivate, edPublic
let edPublic;
try {
let pair = Nacl.sign.keyPair.fromSeed(Nacl.util.decodeBase64(curvePrivate));
edPublic = Nacl.util.encodeBase64(pair.publicKey);
@ -689,8 +691,6 @@ define([
const keyPair = Nacl.box.keyPair();
const newKeyPub = Nacl.util.encodeBase64(keyPair.publicKey);
const newKey = Nacl.util.encodeBase64(keyPair.secretKey);
const newEd = Nacl.sign.keyPair.fromSeed(keyPair.secretKey);
const newEdPub = Nacl.util.encodeBase64(newEd.publicKey);
const oldKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
const oldKeyPub = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
@ -832,7 +832,7 @@ define([
reason: 'Deprecated support pad'
}
}, waitFor());
}).nThen((waitFor) => {
}).nThen(() => {
// Call back
cb({success: true});
});
@ -888,7 +888,7 @@ define([
}
moderators = obj[0] || {};
}));
}).nThen((waitFor) => {
}).nThen(() => {
let n = nThen;
Object.keys(moderators).forEach((ed) => {
n = n((waitFor) => {
@ -980,7 +980,7 @@ define([
support.removeClient = function (clientId) {
delete ctx.clients[clientId];
};
support.leavePad = function (padChan) {};
support.leavePad = function () {};
support.addAdminTicket = function (content, cb) {
addAdminTicket(ctx, content, cb);
};

View file

@ -34,7 +34,7 @@ define([
Util,
Hash,
Sidebar,
Support,
Support
)
{
var APP = {};
@ -61,10 +61,10 @@ define([
var andThen = function (common, $container, linkedTicket) {
const sidebar = Sidebar.create(common, 'support', $container);
const blocks = sidebar.blocks;
// Support panel functions
let open = [];
let refreshAll = function () {};
let refresh = ($container, type) => {
APP.module.execCommand('LIST_TICKETS_ADMIN', {
type: type
@ -110,7 +110,6 @@ define([
};
const onShow = function (ticket, channel, data, done) {
let supportKey = data.supportKey;
APP.module.execCommand('LOAD_TICKET_ADMIN', {
channel: channel,
curvePublic: data.authorKey,
@ -143,8 +142,7 @@ define([
});
done();
};
const onReply = function (ticket, channel, data, form, cb) {
// XXX TODO
const onReply = function (ticket, channel, data, form) {
var formData = APP.support.getFormData(form);
APP.module.execCommand('REPLY_TICKET_ADMIN', {
channel: channel,
@ -208,7 +206,7 @@ define([
};
let activeContainer, pendingContainer, closedContainer;
var refreshAll = function () {
refreshAll = function () {
refresh($(activeContainer), 'active');
refresh($(pendingContainer), 'pending');
refresh($(closedContainer), 'closed');
@ -256,16 +254,16 @@ define([
}
});
sidebar.addItem('active-list', cb => {
let div = activeContainer = h('div.cp-support-container'); // XXX block
cb(div);
activeContainer = h('div.cp-support-container'); // XXX block
cb(activeContainer);
});
sidebar.addItem('pending-list', cb => {
let div = pendingContainer = h('div.cp-support-container'); // XXX block
cb(div);
pendingContainer = h('div.cp-support-container');
cb(pendingContainer);
});
sidebar.addItem('closed-list', cb => {
let div = closedContainer = h('div.cp-support-container'); // XXX block
cb(div);
closedContainer = h('div.cp-support-container');
cb(closedContainer);
}, { noTitle: true, noHint: true });
refreshAll();

View file

@ -161,9 +161,6 @@ define([
var list = h('div.cp-support-container');
var $list = $(list);
let activeForm = {}; // .channel and .form
let refresh = function () {
const onClose = function (ticket, channel, data) {
APP.supportModule.execCommand('CLOSE_TICKET', {
@ -175,7 +172,7 @@ define([
refresh();
});
};
const onReply = function (ticket, channel, data, form, cb) {
const onReply = function (ticket, channel, data, form) {
var formData = APP.support.getFormData(form);
APP.supportModule.execCommand('REPLY_TICKET', {
channel: channel,
@ -187,7 +184,7 @@ define([
refresh();
});
};
const onDelete = function (ticket, channel, data) {
const onDelete = function (ticket, channel) {
APP.supportModule.execCommand('DELETE_TICKET', {
channel: channel
}, function (obj) {
@ -213,8 +210,6 @@ define([
$list.empty();
obj.tickets.forEach((data) => {
var title = data.title;
var time = data.time;
var messages = data.messages;
var first = messages[0];
first.id = data.id;
@ -238,17 +233,10 @@ define([
});
};
var button = h('button.btn.btn-primary', 'refresh'); // XXX
Util.onClickEnter($(button), function () {
refresh();
});
let _refresh = Util.throttle(refresh, 500);;
let _refresh = Util.throttle(refresh, 500);
events.UPDATE_TICKET.reg(_refresh);
refresh();
$div.append([
button,
list
]);
$div.append(list);
return $div;
};

View file

@ -300,7 +300,7 @@ define([
};
var makeTicket = function (ctx, opts) {
let { id, content, form, onShow, onHide, onClose, onReply, onForm, onDelete } = opts;
let { id, content, form, onShow, onHide, onClose, onReply, onDelete } = opts;
var common = ctx.common;
var metadataMgr = common.getMetadataMgr();
var privateData = metadataMgr.getPrivateData();
@ -342,6 +342,7 @@ define([
let visible = false;
adminOpen = function (force) {
var $ticket = $(ticket);
$show.prop('disabled', 'disabled');
if (visible && !force) {
$ticket.toggleClass('cp-not-loaded', true);
@ -360,7 +361,7 @@ define([
});
};
Util.onClickEnter($show, adminOpen);
adminActions = h('span.cp-support-title-buttons', [ url, show ])
adminActions = h('span.cp-support-title-buttons', [ url, show ]);
}
let isPremium = content.premium ? '.cp-support-ispremium' : '';
@ -401,9 +402,7 @@ define([
var oldData = form ? getFormData(ctx, form) : {};
form = undefined;
var newForm = makeForm(ctx, oldData, function () {
onReply(ticket, id, content, newForm, function () {
$(actions).css('display', '');
});
onReply(ticket, id, content, newForm);
}, content.title, true);
$(newForm).attr('data-id', id);
$ticket.append(newForm);