[ABANDONED] API server for Flexor social network.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

159 lines
4.5 KiB

import {
FastifyInstance,
Plugin,
DefaultQuery,
DefaultParams,
DefaultHeaders,
DefaultBody,
RouteShorthandOptions,
} from 'fastify'
import { Server, IncomingMessage, ServerResponse } from 'http'
import { MEDIA_PARTITION_KEY } from '../../constants'
import { errorSchema } from '../../schemas'
import { containerFor, getItem } from '../../lib/database'
import { badRequestError, serverError } from '../../lib/errors'
import { deleteMedia, generateSAS, getBlobUrl } from '../../lib/media'
import { createId } from '../../lib/utils'
import { Media } from '../../types/collections'
import { PluginOptions } from '../../types'
function getSASRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
const options: RouteShorthandOptions = {
schema: {
description: 'Get a shared access signature.',
tags: ['media'],
response: {
200: {
type: 'object',
properties: {
sas: { type: 'string' },
blobUrl: { type: 'string' },
id: { type: 'string' },
},
},
},
},
}
server.get<DefaultQuery, DefaultParams, DefaultHeaders, DefaultBody>('/v1/sas', options, async () => {
return {
sas: generateSAS('arcw', 5),
blobUrl: getBlobUrl(),
id: createId(),
}
})
}
function addRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
interface Body {
name: string
size: number
type: string
originalName: string
}
const options: RouteShorthandOptions = {
schema: {
description: 'Create a Media item.',
tags: ['media'],
body: {
type: 'object',
required: ['name', 'size', 'type', 'originalName'],
properties: {
name: { type: 'string' },
size: { type: 'number' },
type: { type: 'string' },
originalName: { type: 'string' },
},
},
response: {
204: {
description: 'Media item created.',
type: 'object',
},
400: errorSchema,
},
},
}
server.post<DefaultQuery, DefaultParams, DefaultHeaders, Body>('/v1/media', options, async (request, reply) => {
if (!server.database) return serverError(reply)
const { name, size, type, originalName } = request.body
const container = containerFor(server.database.client, 'Media')
const item = await getItem<Media>({
container,
id: name,
partitionKey: MEDIA_PARTITION_KEY,
})
reply.code(204)
if (item) return
await container.items.create<Media>({
id: name,
pk: MEDIA_PARTITION_KEY,
size,
type,
originalName,
attached: false,
created: Date.now(),
})
})
}
function deleteRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
interface Params {
name: string
}
const options: RouteShorthandOptions = {
schema: {
description: 'Delete a media item.',
tags: ['media'],
querystring: {
type: 'object',
required: ['name'],
properties: {
name: { type: 'string' },
},
},
response: {
204: {
description: 'Media item deleted.',
type: 'object',
},
400: errorSchema,
},
},
}
server.delete<DefaultQuery, Params, DefaultHeaders, DefaultBody>('/v1/media', options, async (request, reply) => {
if (!server.database) return serverError(reply)
const mediaItem = containerFor(server.database.client, 'Media').item(request.query.name, MEDIA_PARTITION_KEY)
const { resource: media } = await mediaItem.read<Media>()
if (!media) return badRequestError(reply)
reply.code(204)
if (media.attached) return
await mediaItem.delete()
await deleteMedia(request.body.name)
})
}
const plugin: Plugin<Server, IncomingMessage, ServerResponse, PluginOptions> = async server => {
getSASRoute(server)
addRoute(server)
deleteRoute(server)
}
export default plugin