fix(video): logo overlays must belong to the workspace; drop debug stderr
- produceVideo checks every logo overlay key against the workspace's media_assets, group_assets or branding logo before queueing; a well-formed content address alone no longer suffices. - Remove MEDIA_DEBUG_STDERR=1 from the production compose: it wrote raw ffmpeg stderr to an unrotated file, bypassing redaction.
This commit is contained in:
parent
dd5a6c8b35
commit
1b58768738
4 changed files with 41 additions and 1 deletions
|
|
@ -381,6 +381,7 @@ export class VideoService {
|
|||
const created = await this.dependencies.tenantTransaction(workspaceId, async (client) => {
|
||||
const source = await client.query("SELECT * FROM video_assets WHERE id = $1", [assetId]);
|
||||
if (source.rowCount !== 1) throw new NotFoundException(`video ${assetId} not found`);
|
||||
await assertLogoKeysOwned(client, workspaceId, request);
|
||||
const jobResult = await client.query(
|
||||
`INSERT INTO video_processing_jobs (workspace_id, video_asset_id, state, kind, input_json)
|
||||
VALUES ($1, $2, 'queued', $3, $4::jsonb) RETURNING *`,
|
||||
|
|
@ -595,3 +596,25 @@ function decodeCursor(cursor: string): VideoCursor {
|
|||
function isUuid(value: string): boolean {
|
||||
return /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Storage keys are content-addressed in one shared bucket, so a well-formed key
|
||||
* alone proves nothing about who owns the object. A logo overlay may only use
|
||||
* an image this workspace holds: an attachment, a group asset or its branding.
|
||||
*/
|
||||
async function assertLogoKeysOwned(
|
||||
client: { query: (sql: string, values: unknown[]) => Promise<{ rowCount: number | null }> },
|
||||
workspaceId: string,
|
||||
request: ProduceRequest,
|
||||
): Promise<void> {
|
||||
const keys = [...new Set((request.overlays ?? []).flatMap((overlay) => (overlay.logoStorageKey === undefined ? [] : [overlay.logoStorageKey])))];
|
||||
for (const key of keys) {
|
||||
const owned = await client.query(
|
||||
`SELECT 1 WHERE EXISTS (SELECT 1 FROM media_assets WHERE storage_key = $1 AND workspace_id = $2)
|
||||
OR EXISTS (SELECT 1 FROM group_assets WHERE asset_id = $1 AND workspace_id = $2)
|
||||
OR EXISTS (SELECT 1 FROM workspaces WHERE id = $2 AND branding->>'logoAssetKey' = $1)`,
|
||||
[key, workspaceId],
|
||||
);
|
||||
if (owned.rowCount !== 1) throw new BadRequestException("logoStorageKey is not an image of this collective");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue