openvibers/openvibe.actor Commits

Actor's new chat: the share-defaults form is drawn, not printed as its markup (#344)

OP OpenVibers committed 5 days ago · df174aff1a · 2 files, +5 −1

The owner's phone screenshot of openvibe.actor/chat showed the New runs share form as raw HTML text under the
composer. The form is built with html`` and turned into a string, then put into the page's html`` again, which
escaped it. It is our own markup with its values already escaped, so it goes in with raw(). chat.test checks the
form is on the page and that no escaped copy is.

Changes

ddiff --git a/server/http/chat-pages.js b/server/http/chat-pages.js
iindex c6bfc55..87e9c0e 100644
---- a/server/http/chat-pages.js
++++ b/server/http/chat-pages.js
@@@ -587,6 +587,7 @@ ${modelChip(model)}
const turnHtmls = await Promise.all(turns.map((t) => turnHtml(t, { files: fileMap.get(t.id) || [], readOnly: shared })));
const title = first ? clip(first.task, 60) : 'New chat';
const actions = row ? String(shareButton(row, !shared)) : '';
++ // Our own markup (its values escaped by html``): drawn with raw(), never printed as text (11-08: it was).
const defaults = !shared && !row ? String(await defaultsHtml(requester)) : '';
return send(res, status, {
viewer: req.viewer, config, path: req.originalUrl, title, app: true, noReferrer: true,
@@@ -603,7 +604,7 @@ ${modelChip(model)}
composer: shared ? '' : String(html`${canvasDoc ? canvasPhone(canvasDoc) : ''}${composer({ parent: lastTurn ? lastTurn.id : null, mode: lastTurn ? lastTurn.mode : 'balanced', busy, working: lastTurn && OPEN.includes(lastTurn.state) ? lastTurn.id : null, problem, text, model, allowance: leftLine(config.allowance, today) })}`),
panel: canvasDoc ? String(canvasWide(canvasDoc)) : '',
label: first ? 'Conversation' : 'New chat',
-- }))}${defaults}${shared ? html`<p class="ct-shared-note">This run was shared with you. Only its owner can carry it on.</p>` : ''}</div>`,
++ }))}${raw(defaults)}${shared ? html`<p class="ct-shared-note">This run was shared with you. Only its owner can carry it on.</p>` : ''}</div>`,
});
}
ddiff --git a/test/chat.test.js b/test/chat.test.js
iindex ff7b2c8..467e3bf 100644
---- a/test/chat.test.js
++++ b/test/chat.test.js
@@@ -53,6 +53,9 @@ const LOC = /^\/chat\/(tsk_[0-9A-HJKMNP-TV-Z]{26})#t-\1$/;
const r = await t.get('/chat', { as: kim });
assert.strictEqual(r.status, 200);
assert.match(r.text, /<h2>What should Actor do\?<\/h2>/);
++ // The new runs' share default is a form on the page, never its markup printed as text (11-08, the owner's screenshot).
++ assert.match(r.text, /<form class="ct-share-defaults" method="post" action="\/chat\/defaults">/);
++ assert.ok(!/&lt;form class=&quot;ct-share-defaults/.test(r.text), 'the share-defaults form is not escaped into text');
assert.strictEqual((r.text.match(/data-ovt-starter="/g) || []).length, 8, 'the starters fill the kit\'s composer');
['Find a flight', 'Is this true?', 'Best deal', 'Watch for it', 'Plan a trip', 'Make a list'].forEach((k) => assert.ok(r.text.includes(`<b>${k}</b>`), k));
assert.ok(!/Who handles the mail/.test(r.text), 'not the old DNS example (the owner: "people aren\'t gonna use it for that")');