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:
@@ -0,0 +1,26 @@
|
||||
import BunSQLite from "@moduletrace/bun-sqlite";
|
||||
import type { BUN_SQLITE_COBBLE_MEDIA } from "@/db/types/db";
|
||||
|
||||
type Params = {
|
||||
media_id: number | string;
|
||||
/**
|
||||
* Who it has to belong to: a bot may only show a picture the user the
|
||||
* run is for uploaded, never someone else's.
|
||||
*/
|
||||
user_id: number | string;
|
||||
};
|
||||
|
||||
/**
|
||||
* One of a user's own media rows, for use as a bot's or workspace's
|
||||
* picture, or null when it isn't theirs (or no longer exists). The file
|
||||
* type is checked by the caller (`resolveWorkspacePicture`), so a
|
||||
* document is never taken as a picture.
|
||||
*/
|
||||
export default async function grabOwnPictureMedia({ media_id, user_id }: Params) {
|
||||
const res = await BunSQLite.sql<BUN_SQLITE_COBBLE_MEDIA>({
|
||||
sql: `SELECT * FROM media WHERE id = ? AND user_id = ? LIMIT 1`,
|
||||
values: [Number(media_id), Number(user_id)],
|
||||
});
|
||||
|
||||
return res.payload?.[0] || null;
|
||||
}
|
||||
@@ -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(() => {});
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user