34 lines
2.1 KiB
JavaScript
34 lines
2.1 KiB
JavaScript
const { UUID, failure } = require('./generatedImages');
|
|
function references(text) {
|
|
const ids = new Set();
|
|
for (const match of String(text || '').matchAll(/\/api\/generated-images\/([a-zA-Z0-9%-]+)/g)) {
|
|
if (!UUID.test(match[1])) throw failure(400, 'Invalid generated image reference');
|
|
ids.add(match[1]);
|
|
}
|
|
return [...ids];
|
|
}
|
|
async function validateChat(db, payload, owner) {
|
|
const ids = new Set([...references(payload.generatedImage), ...references(payload.lastAnswer)]);
|
|
for (const job of payload.generatedImageJobs || []) ids.add(job.jobId);
|
|
for (const message of payload.messages) {
|
|
for (const job of message.imageJobs || []) ids.add(job.jobId);
|
|
for (const id of references(message.content)) ids.add(id);
|
|
}
|
|
if (!ids.size) return;
|
|
const rows = await db.query("SELECT id FROM generated_image_jobs WHERE id=ANY($1::uuid[]) AND owner_id=$2 AND workflow='clinical_assistant'", [[...ids], owner]);
|
|
if (rows.rows.length !== ids.size) throw failure(403, 'Saved image references must belong to this account and Clinical Assistant');
|
|
}
|
|
// Called INSIDE the content write transaction: publication and grants commit together.
|
|
async function validateLearning(client, body, owner, contentId) {
|
|
const ids = references(body);
|
|
if (!ids.length) return ids;
|
|
const rows = await client.query(`SELECT j.id FROM generated_image_jobs j WHERE j.id=ANY($1::uuid[]) AND j.workflow='learning_hub' AND j.stage='done'
|
|
AND (j.owner_id=$2 OR EXISTS (SELECT 1 FROM generated_image_links l WHERE l.asset_id=j.id AND l.content_id=$3)) FOR SHARE`, [ids, owner, contentId || null]);
|
|
if (rows.rows.length !== ids.length) throw failure(403, 'Only your Learning Hub assets, or assets already attached to this content, may be attached. Clinical/private-chat images cannot be published.');
|
|
return ids;
|
|
}
|
|
async function setLinks(client, contentId, ids) {
|
|
await client.query('DELETE FROM generated_image_links WHERE content_id=$1', [contentId]);
|
|
for (const id of ids) await client.query('INSERT INTO generated_image_links(asset_id,content_id) VALUES($1,$2)', [id, contentId]);
|
|
}
|
|
module.exports = { references, validateChat, validateLearning, setLinks };
|