Let the coordinator set a workspace's picture
CI / check (push) Canceled after 0s

update_workspace now takes an image media id (or null to remove the
picture). updateWorkspace writes image_media_id through
resolveWorkspacePicture, which only accepts the caller's own image and
deletes the picture it replaced, so a bot can never show someone else's
file or drop a picture it is still using.
This commit is contained in:
2026-10-22 21:10:06 +01:00
parent 34667581b6
commit a5eb2b6a95
6 changed files with 221 additions and 10 deletions
@@ -8,6 +8,9 @@ import assertPromptLength from "@/src/utils/assert-prompt-length";
import grabUserWorkspace from "./grab-user-workspace";
import _ from "lodash";
import assertCrewManager from "@/src/functions/backend/db/access/assert-crew-manager";
import deleteMedia from "@/src/functions/backend/db/media/delete-media";
import grabOwnPictureMedia from "@/src/functions/backend/db/profile-images/grab-own-picture-media";
import resolveWorkspacePicture from "@/src/utils/resolve-workspace-picture";
type Params = {
user_id: number | string;
@@ -18,12 +21,19 @@ type Params = {
data: Pick<
BUN_SQLITE_COBBLE_WORKSPACES,
"name" | "description" | "system_prompt" | "archived"
>;
> & {
/**
* A new picture (a `media` id of the user's own), null to remove
* it, or undefined to leave it alone.
*/
image_media_id?: number | null;
};
};
/**
* Updates one of the user's workspaces. Its `system_prompt` is shared
* context for every bot in it.
* context for every bot in it, and `image_media_id` its picture: a media
* id replaces it (the old picture is deleted), null removes it.
*/
export default async function updateWorkspace({
user_id,
@@ -40,6 +50,15 @@ export default async function updateWorkspace({
throw new AppError(`Workspace not found.`);
}
const image_media_id = resolveWorkspacePicture({
requested: data.image_media_id,
current: workspace.image_media_id,
media:
data.image_media_id == null
? null
: await grabOwnPictureMedia({ media_id: data.image_media_id, user_id }),
});
const res = await BunSQLite.update<
BUN_SQLITE_COBBLE_WORKSPACES,
(typeof BunSQLiteTables)[number]
@@ -56,6 +75,7 @@ export default async function updateWorkspace({
description: data.description,
system_prompt: data.system_prompt,
archived: data.archived,
image_media_id,
},
_.isUndefined,
),
@@ -64,4 +84,19 @@ export default async function updateWorkspace({
if (!res.success) {
throw new Error(`Couldn't update the workspace: ${res.msg}`);
}
/**
* The picture is written, so the one it replaced isn't shown anywhere
* any more.
*/
if (
image_media_id !== undefined &&
workspace.image_media_id &&
Number(workspace.image_media_id) != Number(image_media_id)
) {
await deleteMedia({
id: workspace.image_media_id,
user_id: Number(user_id),
}).catch(() => {});
}
}