From 5e6a9a5752a6257cdfcc9f96152f06e50a24131f Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Thu, 11 Jun 2026 11:44:01 +0000 Subject: [PATCH] fix: limit client portal data exposure --- backend/src/routes/coaching.js | 51 +++++++++++++++++++++++++++++----- 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/backend/src/routes/coaching.js b/backend/src/routes/coaching.js index 4ef8d08..2670b95 100644 --- a/backend/src/routes/coaching.js +++ b/backend/src/routes/coaching.js @@ -27,10 +27,33 @@ function isClientUser(req) { function portalClientIncludes() { return [ - { model: db.sessions, as: "sessions", where: { status: "shared" }, required: false, order: [["session_at", "DESC"]] }, - { model: db.action_items, as: "action_items", order: [["due_at", "ASC"]] }, - { model: db.resources, as: "resources", where: { is_shared: true }, required: false }, - { model: db.prep_briefs, as: "prep_briefs", order: [["updatedAt", "DESC"]] }, + { + model: db.sessions, + as: "sessions", + attributes: ["id", "title", "session_at", "status", "shared_client_notes"], + where: { status: "shared" }, + required: false, + order: [["session_at", "DESC"]], + }, + { + model: db.action_items, + as: "action_items", + attributes: ["id", "title", "due_at", "status"], + order: [["due_at", "ASC"]], + }, + { + model: db.resources, + as: "resources", + attributes: ["id", "title", "description", "url", "resource_type", "is_shared"], + where: { is_shared: true }, + required: false, + }, + { + model: db.prep_briefs, + as: "prep_briefs", + attributes: ["id", "next_session_at", "client_reflection", "client_reflection_at", "status"], + order: [["updatedAt", "DESC"]], + }, ]; } @@ -1007,7 +1030,10 @@ router.get( return; } - if (isClientUser(req) && session.client?.email !== req.currentUser.email) { + if ( + isClientUser(req) && + (session.status !== "shared" || session.client?.email !== req.currentUser.email) + ) { res.status(404).send({ error: "session_not_found" }); return; } @@ -1315,7 +1341,12 @@ router.patch( updatedById: req.currentUser.id, }); - res.status(200).send(actionItem); + res.status(200).send({ + id: actionItem.id, + title: actionItem.title, + due_at: actionItem.due_at, + status: actionItem.status, + }); }), ); @@ -1379,7 +1410,13 @@ router.post( }); } - res.status(200).send(prepBrief); + res.status(200).send({ + id: prepBrief.id, + next_session_at: prepBrief.next_session_at, + client_reflection: prepBrief.client_reflection, + client_reflection_at: prepBrief.client_reflection_at, + status: prepBrief.status, + }); }), );