Changeset View
Changeset View
Standalone View
Standalone View
keyserver/src/creators/upload-creator.js
// @flow | // @flow | ||||
import crypto from 'crypto'; | import crypto from 'crypto'; | ||||
import type { | import type { | ||||
MediaType, | MediaType, | ||||
UploadMultimediaResult, | UploadMultimediaResult, | ||||
Dimensions, | Dimensions, | ||||
} from 'lib/types/media-types.js'; | } from 'lib/types/media-types.js'; | ||||
import { ServerError } from 'lib/utils/errors.js'; | import { ServerError } from 'lib/utils/errors.js'; | ||||
import createIDs from './id-creator.js'; | import createIDs from './id-creator.js'; | ||||
import { dbQuery, SQL } from '../database/database.js'; | import { dbQuery, SQL } from '../database/database.js'; | ||||
import { getUploadURL } from '../fetchers/upload-fetchers.js'; | import { makeUploadURI } from '../fetchers/upload-fetchers.js'; | ||||
import type { Viewer } from '../session/viewer.js'; | import type { Viewer } from '../session/viewer.js'; | ||||
type UploadContent = | |||||
| { | |||||
+storage: 'keyserver', | |||||
+buffer: Buffer, | |||||
} | |||||
| { | |||||
+storage: 'blob_service', | |||||
+blobHolder: string, | |||||
}; | |||||
export type UploadInput = { | export type UploadInput = { | ||||
name: string, | +name: string, | ||||
mime: string, | +mime: string, | ||||
mediaType: MediaType, | +mediaType: MediaType, | ||||
buffer: Buffer, | +content: UploadContent, | ||||
dimensions: Dimensions, | +dimensions: Dimensions, | ||||
loop: boolean, | +loop: boolean, | ||||
encryptionKey?: string, | +encryptionKey?: string, | ||||
}; | }; | ||||
async function createUploads( | async function createUploads( | ||||
viewer: Viewer, | viewer: Viewer, | ||||
uploadInfos: $ReadOnlyArray<UploadInput>, | uploadInfos: $ReadOnlyArray<UploadInput>, | ||||
): Promise<UploadMultimediaResult[]> { | ): Promise<UploadMultimediaResult[]> { | ||||
if (!viewer.loggedIn) { | if (!viewer.loggedIn) { | ||||
throw new ServerError('not_logged_in'); | throw new ServerError('not_logged_in'); | ||||
} | } | ||||
const ids = await createIDs('uploads', uploadInfos.length); | const ids = await createIDs('uploads', uploadInfos.length); | ||||
const uploadRows = uploadInfos.map(uploadInfo => { | const uploadRows = uploadInfos.map(uploadInfo => { | ||||
const id = ids.shift(); | const id = ids.shift(); | ||||
const secret = crypto.randomBytes(8).toString('hex'); | const secret = crypto.randomBytes(8).toString('hex'); | ||||
const { dimensions, mediaType, loop, encryptionKey } = uploadInfo; | const { content, dimensions, mediaType, loop, encryptionKey } = uploadInfo; | ||||
const buffer = | |||||
content.storage === 'keyserver' ? content.buffer : Buffer.alloc(0); | |||||
const blobHolder = | |||||
content.storage === 'blob_service' ? content.blobHolder : undefined; | |||||
const uri = makeUploadURI(blobHolder, id, secret); | |||||
return { | return { | ||||
uploadResult: { | uploadResult: { | ||||
id, | id, | ||||
uri: getUploadURL(id, secret), | uri, | ||||
dimensions, | dimensions, | ||||
mediaType, | mediaType, | ||||
loop, | loop, | ||||
}, | }, | ||||
insert: [ | insert: [ | ||||
id, | id, | ||||
viewer.userID, | viewer.userID, | ||||
mediaType, | mediaType, | ||||
uploadInfo.name, | uploadInfo.name, | ||||
uploadInfo.mime, | uploadInfo.mime, | ||||
uploadInfo.buffer, | buffer, | ||||
secret, | secret, | ||||
Date.now(), | Date.now(), | ||||
JSON.stringify({ ...dimensions, loop, encryptionKey }), | JSON.stringify({ ...dimensions, loop, blobHolder, encryptionKey }), | ||||
], | ], | ||||
}; | }; | ||||
}); | }); | ||||
const insertQuery = SQL` | const insertQuery = SQL` | ||||
INSERT INTO uploads(id, uploader, type, filename, | INSERT INTO uploads(id, uploader, type, filename, | ||||
mime, content, secret, creation_time, extra) | mime, content, secret, creation_time, extra) | ||||
VALUES ${uploadRows.map(({ insert }) => insert)} | VALUES ${uploadRows.map(({ insert }) => insert)} | ||||
`; | `; | ||||
await dbQuery(insertQuery); | await dbQuery(insertQuery); | ||||
return uploadRows.map(({ uploadResult }) => uploadResult); | return uploadRows.map(({ uploadResult }) => uploadResult); | ||||
} | } | ||||
export default createUploads; | export default createUploads; |