Merge branch 'fixes' into staging

This commit is contained in:
yflory 2026-05-06 13:14:55 +02:00
commit 4159d4a5ce
21 changed files with 64 additions and 56 deletions

View File

@ -7,9 +7,10 @@ const Invitation = module.exports;
const Invite = require('../storage/invite');
const Util = require("../common-util");
const Users = require("./users");
const Crypto = require('node:crypto');
const getUid = () => {
return Util.uid() + Util.uid() + Util.uid();
return Crypto.randomBytes(18).toString('hex');
};
Invitation.getAll = (Env, cb) => {

View File

@ -129,7 +129,7 @@ var handleCommand = function (Env, req, res) {
COMMANDS[command](Env, body, function (err) {
if (err) {
Env.Log.error('CHALLENGE_COMMAND_EXECUTION_ERROR', {
body: body,
command,
error: Util.serializeError(err),
});
// errors returned from commands are passed back to the client
@ -229,16 +229,6 @@ var handleResponse = function (Env, req, res) {
});
}
// garbage collection can clean this up later
Challenge.delete(Env, txid, function (err) {
if (err) {
Env.Log.error("CHALLENGE_DELETION_ERROR", {
txid: txid,
error: Util.serializeError(err),
});
}
});
var json = Util.tryParse(text);
if (!json) {
@ -284,8 +274,7 @@ var handleResponse = function (Env, req, res) {
u8_publicKey = Util.decodeBase64(publicKey);
} catch (err3) {
Env.Log.error('CHALLENGE_RESPONSE_DECODING_ERROR', {
text: text,
sig: sig,
command: json.command,
publicKey: publicKey,
error: Util.serializeError(err3),
});
@ -305,6 +294,16 @@ var handleResponse = function (Env, req, res) {
});
}
// garbage collection can clean this up later
Challenge.delete(Env, txid, function (err) {
if (err) {
Env.Log.error("CHALLENGE_DELETION_ERROR", {
txid: txid,
error: Util.serializeError(err),
});
}
});
// execute the command
action(Env, json, function (err, content) {
if (err) {

View File

@ -258,7 +258,7 @@ app.use('/ssoauth', (req, res, next) => {
Log.error('E_SSO_WRITE_REQ', err);
return res.sendStatus(500);
}
let value = `samltoken="${token}"; SameSite=Strict; HttpOnly`;
let value = `samltoken="${token}"; SameSite=Strict; HttpOnly; Path=/; Secure`;
res.setHeader('Set-Cookie', value);
next();
});
@ -750,22 +750,6 @@ var send500 = function (res, path) {
});
};
app.get('/api/updatequota', function (req, res) {
if (!Env.accounts_api) {
res.status(404);
return void send404(res);
}
sendMessage({
command: 'UPDATE_QUOTA',
}, (err) => {
if (err) {
res.status(500);
return void send500(res);
}
res.send();
});
});
app.get('/api/profiling', function (req, res) {
if (!Env.enableProfiling) { return void send404(res); }
sendMessage({

View File

@ -89,3 +89,7 @@ Basic.restore = function (Env, archivePath, path, cb) {
cb(err);
});
};
Basic.isValidId = id => {
return id && typeof(id) === "string" && /^[a-zA-Z0-9-+=]+$/.test(id);
};

View File

@ -22,7 +22,9 @@ const Challenge = module.exports;
*/
const pathFromId = function (Env, id) {
if (!id || typeof(id) !== 'string') { return void console.error('CHALLENGE_BAD_ID', id); }
if (!Basic.isValidId(id)) {
return void console.error('CHALLENGE_BAD_ID', id);
}
return Path.join(Env.paths.base, "challenges", id.slice(0, 2), id);
};

View File

@ -17,7 +17,9 @@ const Invite = module.exports;
*/
const pathFromId = function (Env, id) {
if (!id || typeof(id) !== 'string') { return void console.error('INVITE_BAD_ID', id); }
if (!Basic.isValidId(id)) {
return void console.error('INVITE_BAD_ID', id);
}
return Path.join(Env.paths.base, "invitations", id.slice(0, 2), id);
};

View File

@ -28,6 +28,7 @@ so that it can be accessed quickly.
var pathFromId = function (Env, id) {
if (!id || typeof(id) !== 'string') { return; }
id = Util.escapeKeyCharacters(id);
if (!Basic.isValidId(id)) { return; }
return Path.join(Env.paths.base, "mfa", id.slice(0, 2), `${id}.json`);
};

View File

@ -14,7 +14,9 @@ const Moderator = module.exports;
*/
const pathFromId = function (Env, id) {
if (!id || typeof(id) !== 'string') { return void console.error('KNWONUSER_BAD_ID', id); }
if (!Basic.isValidId(id)) {
return void console.error('MODERATOR_BAD_ID', id);
}
return Path.join(Env.paths.base, "support", id.slice(0, 2), id);
};

View File

@ -25,6 +25,7 @@ const Sessions = module.exports;
var pathFromId = function (Env, id, ref) {
if (!id || typeof(id) !== 'string') { return; }
if (!Basic.isValidId(ref)) { return; }
id = Util.escapeKeyCharacters(id);
return Path.join(Env.paths.base, "sessions", id.slice(0, 2), id, ref);
};

View File

@ -20,6 +20,7 @@ The path for the user database is based on their persistent identifier (id) from
var pathFromId = function (Env, id, subPath) {
if (!id || typeof(id) !== 'string') { return; }
id = Util.escapeKeyCharacters(id);
if (!Basic.isValidId(id)) { return; }
return Path.join(Env.paths.base, subPath, id.slice(0, 2), `${id}.json`);
};
var reqPathFromId = function (Env, id) {

View File

@ -14,7 +14,9 @@ const User = module.exports;
*/
const pathFromId = function (Env, id) {
if (!id || typeof(id) !== 'string') { return void console.error('KNWONUSER_BAD_ID', id); }
if (!Basic.isValidId(id)) {
return void console.error('USER_BAD_ID', id);
}
return Path.join(Env.paths.base, "users", id.slice(0, 2), id);
};

10
package-lock.json generated
View File

@ -19,7 +19,7 @@
"chainpad-crypto": "^0.3.0",
"chainpad-listmap": "^1.2.0",
"chainpad-netflux": "^1.3.0",
"chainpad-server": "^5.2.4",
"chainpad-server": "^5.3.0",
"ckeditor": "npm:ckeditor4@~4.22.1",
"codemirror": "^5.19.0",
"connect-gzip-static": "^4.2.1",
@ -1598,7 +1598,9 @@
}
},
"node_modules/chainpad-server": {
"version": "5.2.4"
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/chainpad-server/-/chainpad-server-5.3.1.tgz",
"integrity": "sha512-yDDsN0Oa8ojtNNJRBpqy/AwnRWkettJfGxUxRGZmMf+bbbiKTPWum8ixP9l8UzErTlYR4wzaTZIKmNpWWcyOtg=="
},
"node_modules/ckeditor": {
"name": "ckeditor4",
@ -3537,7 +3539,9 @@
}
},
"node_modules/netflux-websocket": {
"version": "1.3.0",
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/netflux-websocket/-/netflux-websocket-1.3.1.tgz",
"integrity": "sha512-vom3V+3oXf6dnT6UkCkpi76zZLGYNXTaWA0Azg/CsIfMHP66owYynkOFXoZ8N2gaQNoEWMT6msz9xjSOnAH0cw==",
"license": "LGPL-2.1"
},
"node_modules/node-releases": {

View File

@ -22,7 +22,7 @@
"chainpad-crypto": "^0.3.0",
"chainpad-listmap": "^1.2.0",
"chainpad-netflux": "^1.3.0",
"chainpad-server": "^5.2.4",
"chainpad-server": "^5.3.0",
"ckeditor": "npm:ckeditor4@~4.22.1",
"codemirror": "^5.19.0",
"connect-gzip-static": "^4.2.1",

View File

@ -61,7 +61,6 @@ const factory = (Crypto, CPNetflux, Netflux, Util,
nThen(function (waitFor) {
Session.accessKeys.forEach(function (obj) {
Pinpad.create(config.network, obj, waitFor(function (e) {
console.log('done', obj);
if (e) { console.error(e); }
}));
});

View File

@ -62,7 +62,7 @@ const factory = (SRpc, Channel, Util) => {
} catch (e) {
console.error('Error in webworker when executing query ' + q);
console.error(e);
console.log(data);
//console.log(data);
}
if (q === "DISCONNECT") {
onClose();
@ -99,7 +99,7 @@ const factory = (SRpc, Channel, Util) => {
} catch (e) {
console.error('Error in webworker when executing query JOIN_PAD');
console.error(e);
console.log(data);
//console.log(data);
}
});
chan.on('SEND_PAD_MSG', function (msg, cb) {
@ -112,7 +112,7 @@ const factory = (SRpc, Channel, Util) => {
} catch (e) {
console.error('Error in webworker when executing query SEND_PAD_MSG');
console.error(e);
console.log(data);
//console.log(data);
}
});

View File

@ -116,7 +116,6 @@ const factory = (Crypto, Hash, Util, Realtime, Messaging,
var getChannelMessagesSince = function (ctx, channel, data, keys) {
var network = ctx.store.network;
console.log('Fetching [%s] messages since [%s]', channel.id, data.lastKnownHash || '');
if (channel.isPadChat || channel.isTeamChat) {
// We need to use GET_HISTORY_RANGE to make sure we won't get the full history

View File

@ -170,7 +170,6 @@ const factory = (Util, Hash, Constants, Realtime,
ctx.emit('UPDATE', ctx.listmap.proxy, ctx.clients);
};
profile.execCommand = function (clientId, obj, cb) {
console.log(obj);
var cmd = obj.cmd;
var data = obj.data;
if (cmd === 'SUBSCRIBE') {

View File

@ -213,7 +213,6 @@ define([
opt.channelHex = secret.channel;
}
console.warn(opt);
return opt;
};

View File

@ -120,6 +120,7 @@ var factory = function (Util) {
var iframe = document.createElement('iframe');
if (cfg.pdf.viewer) { // PDFJS
var viewerUrl = cfg.pdf.viewer + '?file=' + url;
iframe.setAttribute('sandbox', 'allow-scripts allow-downloads allow-same-origin');
iframe.src = viewerUrl + '#' + window.encodeURIComponent(metadata.name);
iframe.onload = function () {
if (!metadata.name) { return; }
@ -574,7 +575,11 @@ var factory = function (Util) {
var copyAttributes = function (origin, dest) {
Object.keys(origin.attributes).forEach(function (i) {
if (!/^data-attr/.test(origin.attributes[i].name)) { return; }
var name = origin.attributes[i].name.slice(10);
var name = origin.attributes[i].name.slice(10).toLowerCase();
// Ignore attributes filtered out by the sanitizer
if (name === "src") { return; }
if (name === "srcdoc") { return; }
if (/^on/i.test(name)) { return; }
var value = origin.attributes[i].value;
dest.setAttribute(name, value);
});

View File

@ -5,6 +5,8 @@
(function () {
'use strict';
var factory = function (/*Hash*/) {
let devMode = false;
try { devMode = localStorage.CryptPad_dev === "1"; } catch (e) {}
// This API is used to load a CryptPad editor for a provided document in
// an external platform.
@ -48,7 +50,7 @@
var msg = data.msg;
var txid = data.txid;
if (commands[msg.q]) {
console.warn('OUTER RECEIVED QUERY', msg.q, msg.data);
if (devMode) { console.warn('OUTER RECEIVED QUERY', msg.q, msg.data); }
commands[msg.q](msg.data, function (args) {
_sendCb(txid, args);
});
@ -62,7 +64,7 @@
var txid = getTxid();
if (cb) { handlers[txid] = cb; }
console.warn('OUTER SENT QUERY', q, data);
if (devMode) { console.warn('OUTER SENT QUERY', q, data); }
iWindow.postMessage({ msg: {
q: q,
data: data,

View File

@ -14,7 +14,10 @@ define([
return Math.random().toString(16).replace('0.', '');
};
var init = function () {
console.warn('INIT');
let devMode = false;
try { devMode = localStorage.CryptPad_dev === "1"; } catch (e) {}
if (devMode) { console.warn('INIT'); }
var p = window.parent;
var txid = getTxid();
p.postMessage({ q: 'INTEGRATION_READY', txid: txid }, '*');
@ -86,7 +89,7 @@ define([
http.open('HEAD', url);
http.onreadystatechange = function() {
if (this.readyState === this.DONE) {
console.error(oldKey, this.status);
if (devMode) { console.error(oldKey, this.status); }
if (this.status === 200) {
return cb({state: true});
}
@ -150,7 +153,7 @@ define([
}
if (data.keepOld) { // they provide their own key, we must turn it into a hash
var key = sanitizeKey(data.key) + "000000000000000000000000000000000";
console.warn('KEY', key);
if (devMode) { console.warn('KEY', key); }
let hash = `/2/integration/edit/${key.slice(0,24)}/`;
return void cb({
key: hash,
@ -265,7 +268,7 @@ define([
xhr.responseType = 'blob';
//xhr.setRequestHeader('Content-Type', 'application/json');
xhr.onload = function () {
console.error(this.status);
if (devMode) { console.error(this.status); }
if (this.status === 200) {
cb();
} else {
@ -278,7 +281,7 @@ define([
xhr.send(blob);
};
chan.on('START', function (data, cb) {
console.warn('INNER START', data);
if (devMode) { console.warn('INNER START', data); }
// data.key is a hash
var href = Hash.hashToHref(data.key, data.application);
if (data.editorConfig.lang) {
@ -303,7 +306,7 @@ define([
});
};
console.error(Hash.hrefToHexChannelId(href));
if (devMode) { console.error(Hash.hrefToHexChannelId(href)); }
let startApp = function (blob) {
window.CP_integration_outer = {
pathname: `/${data.application}/`,
@ -336,7 +339,6 @@ define([
path = '/common/onlyoffice/main.js';
}
require([path], function () {
console.warn('SAO REQUIRED');
delete window.CP_integration_outer;
cb();
});