mirror of https://github.com/xwiki-labs/cryptpad
New support: lint compliance and clean XXX
This commit is contained in:
parent
a62dc7cfae
commit
d525852a8f
|
@ -942,16 +942,13 @@ var removeModerator = (Env, Server, cb, data) => {
|
||||||
const id = Array.isArray(data) && data[1];
|
const id = Array.isArray(data) && data[1];
|
||||||
Moderators.delete(Env, id, cb);
|
Moderators.delete(Env, id, cb);
|
||||||
};
|
};
|
||||||
var archiveSupport = (Env, Server, cb, data) => {
|
var archiveSupport = (Env, Server, cb) => {
|
||||||
let supportPinKey = Env.supportPinKey;
|
let supportPinKey = Env.supportPinKey;
|
||||||
console.log(supportPinKey);
|
|
||||||
getPinList(Env, Server, (err, list) => {
|
getPinList(Env, Server, (err, list) => {
|
||||||
console.log(list);
|
|
||||||
if (err) { return void cb(err); }
|
if (err) { return void cb(err); }
|
||||||
let n = nThen;
|
let n = nThen;
|
||||||
list.forEach(id => {
|
list.forEach(id => {
|
||||||
n = n(waitFor => {
|
n = n(waitFor => {
|
||||||
console.log(id);
|
|
||||||
archiveDocument(Env, Server, waitFor(), [null, {id, reason:'DISABLE_SUPPORT'}]);
|
archiveDocument(Env, Server, waitFor(), [null, {id, reason:'DISABLE_SUPPORT'}]);
|
||||||
}).nThen;
|
}).nThen;
|
||||||
});
|
});
|
||||||
|
|
|
@ -389,7 +389,7 @@ commands.SET_BEARER_SECRET = function (Env, args) {
|
||||||
};
|
};
|
||||||
|
|
||||||
// [<command>, <args>, <author>, <time>]
|
// [<command>, <args>, <author>, <time>]
|
||||||
var handleCommand = Decrees.handleCommand = function (Env, line, cb) {
|
var handleCommand = Decrees.handleCommand = function (Env, line) {
|
||||||
var command = line[0];
|
var command = line[0];
|
||||||
var args = line[1];
|
var args = line[1];
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ Basic.readDir = function (Env, path, cb) {
|
||||||
if (!path) { return void pathError(cb); }
|
if (!path) { return void pathError(cb); }
|
||||||
Fs.readdir(path, cb);
|
Fs.readdir(path, cb);
|
||||||
};
|
};
|
||||||
Basic.readDirSync = function (Env, path, cb) {
|
Basic.readDirSync = function (Env, path) {
|
||||||
if (!path) { return []; }
|
if (!path) { return []; }
|
||||||
return Fs.readdirSync(path);
|
return Fs.readdirSync(path);
|
||||||
};
|
};
|
||||||
|
|
|
@ -2932,7 +2932,7 @@ Example
|
||||||
let supportKey = ApiConfig.supportMailboxKey;
|
let supportKey = ApiConfig.supportMailboxKey;
|
||||||
let edPublic = common.getMetadataMgr().getPrivateData().edPublic; // My edPublic
|
let edPublic = common.getMetadataMgr().getPrivateData().edPublic; // My edPublic
|
||||||
let refresh = function () {};
|
let refresh = function () {};
|
||||||
const redraw = function (moderatorsData, oldPrivKey) {
|
const redraw = function (moderatorsData) {
|
||||||
$div.empty();
|
$div.empty();
|
||||||
|
|
||||||
const state = h('div');
|
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) => {
|
const getContactData = (curve) => {
|
||||||
let friends = common.getFriends(true);
|
let friends = common.getFriends(true);
|
||||||
let f = friends[curve || 'me'];
|
let f = friends[curve || 'me'];
|
||||||
|
@ -3029,9 +3014,6 @@ Example
|
||||||
UI.warn(Messages.error);
|
UI.warn(Messages.error);
|
||||||
};
|
};
|
||||||
|
|
||||||
//const oldCrypto = supportKey ? getEncryptor(oldPrivKey) : undefined;
|
|
||||||
//const newCrypto = getEncryptor(priv);
|
|
||||||
|
|
||||||
nThen((waitFor) => {
|
nThen((waitFor) => {
|
||||||
// Add myself to moderator role if not already there
|
// Add myself to moderator role if not already there
|
||||||
let me = getContactData();
|
let me = getContactData();
|
||||||
|
@ -3073,10 +3055,7 @@ Example
|
||||||
}
|
}
|
||||||
|
|
||||||
// User added to support team in database, send them the keys
|
// User added to support team in database, send them the keys
|
||||||
APP.supportModule.execCommand('ADD_MODERATOR', userData, (obj) => {
|
APP.supportModule.execCommand('ADD_MODERATOR', userData, cb);
|
||||||
// XXX IF ERROR, (can't notify) remove from DB?
|
|
||||||
cb();
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const removeModerator = (ed) => {
|
const removeModerator = (ed) => {
|
||||||
|
@ -3093,20 +3072,13 @@ Example
|
||||||
};
|
};
|
||||||
|
|
||||||
Util.onClickEnter($button, function () {
|
Util.onClickEnter($button, function () {
|
||||||
/*
|
|
||||||
if (supportKey) {
|
|
||||||
return void UI.confirm(Messages.admin_supportNewConfirm, function (yes) {
|
|
||||||
if (yes) { generateKey(); }
|
|
||||||
});
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
generateKey();
|
generateKey();
|
||||||
});
|
});
|
||||||
|
|
||||||
const drawModerators = () => {
|
const drawModerators = () => {
|
||||||
if (!supportKey) { return; }
|
if (!supportKey) { return; }
|
||||||
const members = {};
|
const members = {};
|
||||||
const friends = Util.clone(common.getFriends(false))
|
const friends = Util.clone(common.getFriends(false));
|
||||||
Object.keys(moderatorsData).forEach((ed) => {
|
Object.keys(moderatorsData).forEach((ed) => {
|
||||||
let m = moderatorsData[ed];
|
let m = moderatorsData[ed];
|
||||||
members[m.curvePublic] = {
|
members[m.curvePublic] = {
|
||||||
|
@ -3170,10 +3142,9 @@ Example
|
||||||
drawModerators();
|
drawModerators();
|
||||||
};
|
};
|
||||||
refresh = () => {
|
refresh = () => {
|
||||||
let oldKey, moderators;
|
let moderators;
|
||||||
nThen((waitFor) => {
|
nThen((waitFor) => {
|
||||||
APP.supportModule.execCommand('GET_PRIVATE_KEY', {}, waitFor((obj) => {
|
APP.supportModule.execCommand('GET_PRIVATE_KEY', {}, waitFor((obj) => {
|
||||||
oldKey = obj && obj.curvePrivate;
|
|
||||||
supportKey = obj && obj.curvePublic;
|
supportKey = obj && obj.curvePublic;
|
||||||
}));
|
}));
|
||||||
}).nThen((waitFor) => {
|
}).nThen((waitFor) => {
|
||||||
|
@ -3189,7 +3160,7 @@ Example
|
||||||
moderators = response[0];
|
moderators = response[0];
|
||||||
}));
|
}));
|
||||||
}).nThen(() => {
|
}).nThen(() => {
|
||||||
redraw(moderators, oldKey);
|
redraw(moderators);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
refresh();
|
refresh();
|
||||||
|
|
|
@ -2236,7 +2236,7 @@ define([
|
||||||
};
|
};
|
||||||
var $userAdmin = UIElements.createDropdown(dropdownConfigUser);
|
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"]');
|
var $surveyHr = $survey.next('[role="separator"]');
|
||||||
if (!surveyURL) {
|
if (!surveyURL) {
|
||||||
$survey.hide();
|
$survey.hide();
|
||||||
|
|
|
@ -887,7 +887,6 @@ define([
|
||||||
// Update ChainPad doc
|
// Update ChainPad doc
|
||||||
support.updateAdminTicket(content);
|
support.updateAdminTicket(content);
|
||||||
|
|
||||||
// XXX TODO opt out
|
|
||||||
if (Util.find(ctx.store.proxy, ['settings', 'general', 'disableSupportNotif'])) {
|
if (Util.find(ctx.store.proxy, ['settings', 'general', 'disableSupportNotif'])) {
|
||||||
return void cb(true);
|
return void cb(true);
|
||||||
}
|
}
|
||||||
|
@ -912,7 +911,6 @@ define([
|
||||||
handlers['ADD_MODERATOR'] = function (ctx, box, data, cb) {
|
handlers['ADD_MODERATOR'] = function (ctx, box, data, cb) {
|
||||||
var msg = data.msg;
|
var msg = data.msg;
|
||||||
var content = msg.content;
|
var content = msg.content;
|
||||||
var newKey = content.supportKey;
|
|
||||||
|
|
||||||
var support = Util.find(ctx, ['store', 'modules', 'support']);
|
var support = Util.find(ctx, ['store', 'modules', 'support']);
|
||||||
support.updateAdminKey(content, cb);
|
support.updateAdminKey(content, cb);
|
||||||
|
@ -920,7 +918,6 @@ define([
|
||||||
handlers['MODERATOR_NEW_KEY'] = function (ctx, box, data, cb) {
|
handlers['MODERATOR_NEW_KEY'] = function (ctx, box, data, cb) {
|
||||||
var msg = data.msg;
|
var msg = data.msg;
|
||||||
var content = msg.content;
|
var content = msg.content;
|
||||||
var newKey = content.supportKey;
|
|
||||||
|
|
||||||
var support = Util.find(ctx, ['store', 'modules', 'support']);
|
var support = Util.find(ctx, ['store', 'modules', 'support']);
|
||||||
support.updateAdminKey(content, function () {
|
support.updateAdminKey(content, function () {
|
||||||
|
|
|
@ -70,7 +70,7 @@ define([
|
||||||
theirPublic = obj.theirPublic;
|
theirPublic = obj.theirPublic;
|
||||||
myCurve = obj.myCurve;
|
myCurve = obj.myCurve;
|
||||||
}));
|
}));
|
||||||
}).nThen((waitFor) => {
|
}).nThen(() => {
|
||||||
var keys = Crypto.Curve.deriveKeys(theirPublic, myCurve);
|
var keys = Crypto.Curve.deriveKeys(theirPublic, myCurve);
|
||||||
var crypto = Crypto.Curve.createEncryptor(keys);
|
var crypto = Crypto.Curve.createEncryptor(keys);
|
||||||
var cfg = {
|
var cfg = {
|
||||||
|
@ -102,6 +102,7 @@ define([
|
||||||
cfg.onChannelError = cb;
|
cfg.onChannelError = cb;
|
||||||
cfg.onReady = function () {
|
cfg.onReady = function () {
|
||||||
cb(null, all);
|
cb(null, all);
|
||||||
|
close();
|
||||||
};
|
};
|
||||||
cpNf = CpNetflux.start(cfg);
|
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
|
// USER COMMANDS
|
||||||
|
|
||||||
var getMyTickets = function (ctx, data, cId, cb) {
|
var getMyTickets = function (ctx, data, cId, cb) {
|
||||||
|
@ -305,7 +423,7 @@ define([
|
||||||
cb({deleted: true});
|
cb({deleted: true});
|
||||||
};
|
};
|
||||||
|
|
||||||
// ADMIN COMMANDS
|
// MODERATOR COMMANDS
|
||||||
|
|
||||||
var listTicketsAdmin = function (ctx, data, cId, cb) {
|
var listTicketsAdmin = function (ctx, data, cId, cb) {
|
||||||
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
|
if (!ctx.adminRdyEvt) { return void cb({ error: 'EFORBIDDEN' }); }
|
||||||
|
@ -353,7 +471,7 @@ define([
|
||||||
entry.premium = premium;
|
entry.premium = premium;
|
||||||
|
|
||||||
if (senderKey) {
|
if (senderKey) {
|
||||||
entry.lastAdmin = ctx.moderatorKeys.indexOf(senderKey) !== -1
|
entry.lastAdmin = ctx.moderatorKeys.indexOf(senderKey) !== -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cb(res);
|
cb(res);
|
||||||
|
@ -404,6 +522,7 @@ define([
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// Mailbox events
|
// Mailbox events
|
||||||
|
|
||||||
var notifyClient = function (ctx, admin, type, channel) {
|
var notifyClient = function (ctx, admin, type, channel) {
|
||||||
|
@ -416,7 +535,7 @@ define([
|
||||||
|
|
||||||
var addAdminTicket = function (ctx, data, cb) {
|
var addAdminTicket = function (ctx, data, cb) {
|
||||||
// Wait for the chainpad to be ready before adding the data
|
// 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(() => {
|
ctx.adminRdyEvt.reg(() => {
|
||||||
let supportKey;
|
let supportKey;
|
||||||
|
@ -452,13 +571,13 @@ define([
|
||||||
});
|
});
|
||||||
notifyClient(ctx, true, 'NEW_TICKET', data.channel);
|
notifyClient(ctx, true, 'NEW_TICKET', data.channel);
|
||||||
if (ctx.supportRpc) { ctx.supportRpc.pin([data.channel], () => {}); }
|
if (ctx.supportRpc) { ctx.supportRpc.pin([data.channel], () => {}); }
|
||||||
});
|
}, rdmTo);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var updateAdminTicket = function (ctx, data) {
|
var updateAdminTicket = function (ctx, data) {
|
||||||
// Wait for the chainpad to be ready before adding the 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(() => {
|
ctx.adminRdyEvt.reg(() => {
|
||||||
// random timeout to avoid duplication wiht multiple admins
|
// random timeout to avoid duplication wiht multiple admins
|
||||||
|
@ -478,11 +597,11 @@ define([
|
||||||
t.time = data.time;
|
t.time = data.time;
|
||||||
t.lastAdmin = false;
|
t.lastAdmin = false;
|
||||||
notifyClient(ctx, true, 'UPDATE_TICKET', data.channel);
|
notifyClient(ctx, true, 'UPDATE_TICKET', data.channel);
|
||||||
});
|
}, rdmTo);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
var checkAdminTicket = function (ctx, data, cb) {
|
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(() => {
|
ctx.adminRdyEvt.reg(() => {
|
||||||
let doc = ctx.adminDoc.proxy;
|
let doc = ctx.adminDoc.proxy;
|
||||||
|
@ -541,128 +660,11 @@ define([
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
// INITIALIZE ADMIN
|
|
||||||
|
|
||||||
var getPinList = function (ctx) {
|
// ADMIN COMMANDS
|
||||||
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')
|
|
||||||
});
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
let updateServerKey = (ctx, curvePublic, curvePrivate, cb) => {
|
let updateServerKey = (ctx, curvePublic, curvePrivate, cb) => {
|
||||||
let edPrivate, edPublic
|
let edPublic;
|
||||||
try {
|
try {
|
||||||
let pair = Nacl.sign.keyPair.fromSeed(Nacl.util.decodeBase64(curvePrivate));
|
let pair = Nacl.sign.keyPair.fromSeed(Nacl.util.decodeBase64(curvePrivate));
|
||||||
edPublic = Nacl.util.encodeBase64(pair.publicKey);
|
edPublic = Nacl.util.encodeBase64(pair.publicKey);
|
||||||
|
@ -689,8 +691,6 @@ define([
|
||||||
const keyPair = Nacl.box.keyPair();
|
const keyPair = Nacl.box.keyPair();
|
||||||
const newKeyPub = Nacl.util.encodeBase64(keyPair.publicKey);
|
const newKeyPub = Nacl.util.encodeBase64(keyPair.publicKey);
|
||||||
const newKey = Nacl.util.encodeBase64(keyPair.secretKey);
|
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 oldKey = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePrivate']);
|
||||||
const oldKeyPub = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
|
const oldKeyPub = Util.find(proxy, ['mailboxes', 'supportteam', 'keys', 'curvePublic']);
|
||||||
|
@ -832,7 +832,7 @@ define([
|
||||||
reason: 'Deprecated support pad'
|
reason: 'Deprecated support pad'
|
||||||
}
|
}
|
||||||
}, waitFor());
|
}, waitFor());
|
||||||
}).nThen((waitFor) => {
|
}).nThen(() => {
|
||||||
// Call back
|
// Call back
|
||||||
cb({success: true});
|
cb({success: true});
|
||||||
});
|
});
|
||||||
|
@ -888,7 +888,7 @@ define([
|
||||||
}
|
}
|
||||||
moderators = obj[0] || {};
|
moderators = obj[0] || {};
|
||||||
}));
|
}));
|
||||||
}).nThen((waitFor) => {
|
}).nThen(() => {
|
||||||
let n = nThen;
|
let n = nThen;
|
||||||
Object.keys(moderators).forEach((ed) => {
|
Object.keys(moderators).forEach((ed) => {
|
||||||
n = n((waitFor) => {
|
n = n((waitFor) => {
|
||||||
|
@ -980,7 +980,7 @@ define([
|
||||||
support.removeClient = function (clientId) {
|
support.removeClient = function (clientId) {
|
||||||
delete ctx.clients[clientId];
|
delete ctx.clients[clientId];
|
||||||
};
|
};
|
||||||
support.leavePad = function (padChan) {};
|
support.leavePad = function () {};
|
||||||
support.addAdminTicket = function (content, cb) {
|
support.addAdminTicket = function (content, cb) {
|
||||||
addAdminTicket(ctx, content, cb);
|
addAdminTicket(ctx, content, cb);
|
||||||
};
|
};
|
||||||
|
|
|
@ -34,7 +34,7 @@ define([
|
||||||
Util,
|
Util,
|
||||||
Hash,
|
Hash,
|
||||||
Sidebar,
|
Sidebar,
|
||||||
Support,
|
Support
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
var APP = {};
|
var APP = {};
|
||||||
|
@ -61,10 +61,10 @@ define([
|
||||||
|
|
||||||
var andThen = function (common, $container, linkedTicket) {
|
var andThen = function (common, $container, linkedTicket) {
|
||||||
const sidebar = Sidebar.create(common, 'support', $container);
|
const sidebar = Sidebar.create(common, 'support', $container);
|
||||||
const blocks = sidebar.blocks;
|
|
||||||
|
|
||||||
// Support panel functions
|
// Support panel functions
|
||||||
let open = [];
|
let open = [];
|
||||||
|
let refreshAll = function () {};
|
||||||
let refresh = ($container, type) => {
|
let refresh = ($container, type) => {
|
||||||
APP.module.execCommand('LIST_TICKETS_ADMIN', {
|
APP.module.execCommand('LIST_TICKETS_ADMIN', {
|
||||||
type: type
|
type: type
|
||||||
|
@ -110,7 +110,6 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
const onShow = function (ticket, channel, data, done) {
|
const onShow = function (ticket, channel, data, done) {
|
||||||
let supportKey = data.supportKey;
|
|
||||||
APP.module.execCommand('LOAD_TICKET_ADMIN', {
|
APP.module.execCommand('LOAD_TICKET_ADMIN', {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
curvePublic: data.authorKey,
|
curvePublic: data.authorKey,
|
||||||
|
@ -143,8 +142,7 @@ define([
|
||||||
});
|
});
|
||||||
done();
|
done();
|
||||||
};
|
};
|
||||||
const onReply = function (ticket, channel, data, form, cb) {
|
const onReply = function (ticket, channel, data, form) {
|
||||||
// XXX TODO
|
|
||||||
var formData = APP.support.getFormData(form);
|
var formData = APP.support.getFormData(form);
|
||||||
APP.module.execCommand('REPLY_TICKET_ADMIN', {
|
APP.module.execCommand('REPLY_TICKET_ADMIN', {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
|
@ -208,7 +206,7 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
let activeContainer, pendingContainer, closedContainer;
|
let activeContainer, pendingContainer, closedContainer;
|
||||||
var refreshAll = function () {
|
refreshAll = function () {
|
||||||
refresh($(activeContainer), 'active');
|
refresh($(activeContainer), 'active');
|
||||||
refresh($(pendingContainer), 'pending');
|
refresh($(pendingContainer), 'pending');
|
||||||
refresh($(closedContainer), 'closed');
|
refresh($(closedContainer), 'closed');
|
||||||
|
@ -256,16 +254,16 @@ define([
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sidebar.addItem('active-list', cb => {
|
sidebar.addItem('active-list', cb => {
|
||||||
let div = activeContainer = h('div.cp-support-container'); // XXX block
|
activeContainer = h('div.cp-support-container'); // XXX block
|
||||||
cb(div);
|
cb(activeContainer);
|
||||||
});
|
});
|
||||||
sidebar.addItem('pending-list', cb => {
|
sidebar.addItem('pending-list', cb => {
|
||||||
let div = pendingContainer = h('div.cp-support-container'); // XXX block
|
pendingContainer = h('div.cp-support-container');
|
||||||
cb(div);
|
cb(pendingContainer);
|
||||||
});
|
});
|
||||||
sidebar.addItem('closed-list', cb => {
|
sidebar.addItem('closed-list', cb => {
|
||||||
let div = closedContainer = h('div.cp-support-container'); // XXX block
|
closedContainer = h('div.cp-support-container');
|
||||||
cb(div);
|
cb(closedContainer);
|
||||||
}, { noTitle: true, noHint: true });
|
}, { noTitle: true, noHint: true });
|
||||||
refreshAll();
|
refreshAll();
|
||||||
|
|
||||||
|
|
|
@ -161,9 +161,6 @@ define([
|
||||||
var list = h('div.cp-support-container');
|
var list = h('div.cp-support-container');
|
||||||
var $list = $(list);
|
var $list = $(list);
|
||||||
|
|
||||||
|
|
||||||
let activeForm = {}; // .channel and .form
|
|
||||||
|
|
||||||
let refresh = function () {
|
let refresh = function () {
|
||||||
const onClose = function (ticket, channel, data) {
|
const onClose = function (ticket, channel, data) {
|
||||||
APP.supportModule.execCommand('CLOSE_TICKET', {
|
APP.supportModule.execCommand('CLOSE_TICKET', {
|
||||||
|
@ -175,7 +172,7 @@ define([
|
||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onReply = function (ticket, channel, data, form, cb) {
|
const onReply = function (ticket, channel, data, form) {
|
||||||
var formData = APP.support.getFormData(form);
|
var formData = APP.support.getFormData(form);
|
||||||
APP.supportModule.execCommand('REPLY_TICKET', {
|
APP.supportModule.execCommand('REPLY_TICKET', {
|
||||||
channel: channel,
|
channel: channel,
|
||||||
|
@ -187,7 +184,7 @@ define([
|
||||||
refresh();
|
refresh();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
const onDelete = function (ticket, channel, data) {
|
const onDelete = function (ticket, channel) {
|
||||||
APP.supportModule.execCommand('DELETE_TICKET', {
|
APP.supportModule.execCommand('DELETE_TICKET', {
|
||||||
channel: channel
|
channel: channel
|
||||||
}, function (obj) {
|
}, function (obj) {
|
||||||
|
@ -213,8 +210,6 @@ define([
|
||||||
|
|
||||||
$list.empty();
|
$list.empty();
|
||||||
obj.tickets.forEach((data) => {
|
obj.tickets.forEach((data) => {
|
||||||
var title = data.title;
|
|
||||||
var time = data.time;
|
|
||||||
var messages = data.messages;
|
var messages = data.messages;
|
||||||
var first = messages[0];
|
var first = messages[0];
|
||||||
first.id = data.id;
|
first.id = data.id;
|
||||||
|
@ -238,17 +233,10 @@ define([
|
||||||
});
|
});
|
||||||
|
|
||||||
};
|
};
|
||||||
var button = h('button.btn.btn-primary', 'refresh'); // XXX
|
let _refresh = Util.throttle(refresh, 500);
|
||||||
Util.onClickEnter($(button), function () {
|
|
||||||
refresh();
|
|
||||||
});
|
|
||||||
let _refresh = Util.throttle(refresh, 500);;
|
|
||||||
events.UPDATE_TICKET.reg(_refresh);
|
events.UPDATE_TICKET.reg(_refresh);
|
||||||
refresh();
|
refresh();
|
||||||
$div.append([
|
$div.append(list);
|
||||||
button,
|
|
||||||
list
|
|
||||||
]);
|
|
||||||
return $div;
|
return $div;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -300,7 +300,7 @@ define([
|
||||||
};
|
};
|
||||||
|
|
||||||
var makeTicket = function (ctx, opts) {
|
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 common = ctx.common;
|
||||||
var metadataMgr = common.getMetadataMgr();
|
var metadataMgr = common.getMetadataMgr();
|
||||||
var privateData = metadataMgr.getPrivateData();
|
var privateData = metadataMgr.getPrivateData();
|
||||||
|
@ -342,6 +342,7 @@ define([
|
||||||
|
|
||||||
let visible = false;
|
let visible = false;
|
||||||
adminOpen = function (force) {
|
adminOpen = function (force) {
|
||||||
|
var $ticket = $(ticket);
|
||||||
$show.prop('disabled', 'disabled');
|
$show.prop('disabled', 'disabled');
|
||||||
if (visible && !force) {
|
if (visible && !force) {
|
||||||
$ticket.toggleClass('cp-not-loaded', true);
|
$ticket.toggleClass('cp-not-loaded', true);
|
||||||
|
@ -360,7 +361,7 @@ define([
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
Util.onClickEnter($show, adminOpen);
|
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' : '';
|
let isPremium = content.premium ? '.cp-support-ispremium' : '';
|
||||||
|
@ -401,9 +402,7 @@ define([
|
||||||
var oldData = form ? getFormData(ctx, form) : {};
|
var oldData = form ? getFormData(ctx, form) : {};
|
||||||
form = undefined;
|
form = undefined;
|
||||||
var newForm = makeForm(ctx, oldData, function () {
|
var newForm = makeForm(ctx, oldData, function () {
|
||||||
onReply(ticket, id, content, newForm, function () {
|
onReply(ticket, id, content, newForm);
|
||||||
$(actions).css('display', '');
|
|
||||||
});
|
|
||||||
}, content.title, true);
|
}, content.title, true);
|
||||||
$(newForm).attr('data-id', id);
|
$(newForm).attr('data-id', id);
|
||||||
$ticket.append(newForm);
|
$ticket.append(newForm);
|
||||||
|
|
Loading…
Reference in New Issue