openvibers/openvibe.mediahub Commits
Video uploads: the uploader goes in the VOD's meta (Media's user_id is a number) (#68)
Changes
@@@ -94,10 +94,13 @@ function createMediaClient({ config, fetchImpl = globalThis.fetch, log = consolereturn {enabled,-- /** A VOD row for an upload (Media's user_id is the uploader's usr_… subject; MediaHub owns the meaning). */++ /**++ * A VOD row for an upload. Media's user_id is an app-local number (Live's users), so the uploader's usr_… subject++ * goes in the VOD's meta instead; MediaHub's own row is what says whose it is.++ */vodCreate: ({ title, visibility = 'public', ownerSubject }) => call('', {root: vods(), method: 'POST',-- json: { title: String(title || 'Video').slice(0, 300), visibility: ['public', 'unlisted', 'private'].includes(visibility) ? visibility : 'private', user_id: subjectHeader(ownerSubject) },++ json: { title: String(title || 'Video').slice(0, 300), visibility: ['public', 'unlisted', 'private'].includes(visibility) ? visibility : 'private', meta: { source: 'openvibe.video upload', owner_subject: subjectHeader(ownerSubject) } },}),/** One part of the file, appended to the VOD's file in the order sent (segment 1: one continuous file). */vodChunk(vodId, buffer, contentType) {@@@ -110,7 +110,8 @@ async function startMedia({ maxSingle = 256 * 1024 * 1024 } = {}) {if (parts.length === 4 && req.method === 'POST') {const body = JSON.parse(raw.toString('utf8') || '{}');const id = ++vodSeq;-- vods.set(id, { id, title: body.title, visibility: body.visibility, user_id: body.user_id, bytes: Buffer.alloc(0), types: [], status: 'recording' });++ if (body.user_id != null && !/^\d+$/.test(String(body.user_id))) return problem(res, 500, 'vod.create', 'invalid input syntax for type bigint'); // as Media's column refuses it++ vods.set(id, { id, title: body.title, visibility: body.visibility, user_id: body.user_id, meta: body.meta, bytes: Buffer.alloc(0), types: [], status: 'recording' });return json(res, 201, { id });}const v = vods.get(Number(parts[4]));@@@ -83,7 +83,8 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = truconst vod = [...t.media.vods.values()][0];assert.ok(vod.bytes.equals(file), 'Media has the file, byte for byte');assert.deepStrictEqual(vod.types, ['video/mp4', 'video/mp4'], 'QuickTime is sent as MP4');-- assert.strictEqual(vod.user_id, kim.subject);++ assert.strictEqual(vod.user_id, undefined, 'Media\'s user_id is a number: no subject there');++ assert.strictEqual(vod.meta.owner_subject, kim.subject, 'the uploader is in the VOD\'s meta');const done1 = await vreq(t.base, `/api/v1/videos/${id}/complete`, { method: 'POST', cookie: kimCookie });assert.strictEqual(done1.status, 202);assert.strictEqual(done1.json().video.url, `/u/${id}`);
@@ -94,10 +94,13 @@ function createMediaClient({ config, fetchImpl = globalThis.fetch, log = console
@@ -94,10 +94,13 @@ function createMediaClient({ config, fetchImpl = globalThis.fetch, log = console
return {
return {
enabled,
enabled,
- /** A VOD row for an upload (Media's user_id is the uploader's usr_… subject; MediaHub owns the meaning). */
+ /**
+ * A VOD row for an upload. Media's user_id is an app-local number (Live's users), so the uploader's usr_… subject
+ * goes in the VOD's meta instead; MediaHub's own row is what says whose it is.
+ */
vodCreate: ({ title, visibility = 'public', ownerSubject }) => call('', {
vodCreate: ({ title, visibility = 'public', ownerSubject }) => call('', {
root: vods(), method: 'POST',
root: vods(), method: 'POST',
- json: { title: String(title || 'Video').slice(0, 300), visibility: ['public', 'unlisted', 'private'].includes(visibility) ? visibility : 'private', user_id: subjectHeader(ownerSubject) },
+ json: { title: String(title || 'Video').slice(0, 300), visibility: ['public', 'unlisted', 'private'].includes(visibility) ? visibility : 'private', meta: { source: 'openvibe.video upload', owner_subject: subjectHeader(ownerSubject) } },
}),
}),
/** One part of the file, appended to the VOD's file in the order sent (segment 1: one continuous file). */
/** One part of the file, appended to the VOD's file in the order sent (segment 1: one continuous file). */
vodChunk(vodId, buffer, contentType) {
vodChunk(vodId, buffer, contentType) {
@@ -110,7 +110,8 @@ async function startMedia({ maxSingle = 256 * 1024 * 1024 } = {}) {
@@ -110,7 +110,8 @@ async function startMedia({ maxSingle = 256 * 1024 * 1024 } = {}) {
if (parts.length === 4 && req.method === 'POST') {
if (parts.length === 4 && req.method === 'POST') {
const body = JSON.parse(raw.toString('utf8') || '{}');
const body = JSON.parse(raw.toString('utf8') || '{}');
const id = ++vodSeq;
const id = ++vodSeq;
- vods.set(id, { id, title: body.title, visibility: body.visibility, user_id: body.user_id, bytes: Buffer.alloc(0), types: [], status: 'recording' });
+ if (body.user_id != null && !/^\d+$/.test(String(body.user_id))) return problem(res, 500, 'vod.create', 'invalid input syntax for type bigint'); // as Media's column refuses it
+ vods.set(id, { id, title: body.title, visibility: body.visibility, user_id: body.user_id, meta: body.meta, bytes: Buffer.alloc(0), types: [], status: 'recording' });
return json(res, 201, { id });
return json(res, 201, { id });
}
}
const v = vods.get(Number(parts[4]));
const v = vods.get(Number(parts[4]));
@@ -83,7 +83,8 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = tru
@@ -83,7 +83,8 @@ function vreq(base, path, { method = 'GET', cookie, form, json, body, same = tru
const vod = [...t.media.vods.values()][0];
const vod = [...t.media.vods.values()][0];
assert.ok(vod.bytes.equals(file), 'Media has the file, byte for byte');
assert.ok(vod.bytes.equals(file), 'Media has the file, byte for byte');
assert.deepStrictEqual(vod.types, ['video/mp4', 'video/mp4'], 'QuickTime is sent as MP4');
assert.deepStrictEqual(vod.types, ['video/mp4', 'video/mp4'], 'QuickTime is sent as MP4');
- assert.strictEqual(vod.user_id, kim.subject);
+ assert.strictEqual(vod.user_id, undefined, 'Media\'s user_id is a number: no subject there');
+ assert.strictEqual(vod.meta.owner_subject, kim.subject, 'the uploader is in the VOD\'s meta');
const done1 = await vreq(t.base, `/api/v1/videos/${id}/complete`, { method: 'POST', cookie: kimCookie });
const done1 = await vreq(t.base, `/api/v1/videos/${id}/complete`, { method: 'POST', cookie: kimCookie });
assert.strictEqual(done1.status, 202);
assert.strictEqual(done1.status, 202);
assert.strictEqual(done1.json().video.url, `/u/${id}`);
assert.strictEqual(done1.json().video.url, `/u/${id}`);