[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

5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
5 years ago
4 years ago
5 years ago
5 years ago
5 years ago
4 years ago
5 years ago
4 years ago
5 years ago
  1. import {
  2. FastifyInstance,
  3. Plugin,
  4. DefaultQuery,
  5. DefaultParams,
  6. DefaultHeaders,
  7. DefaultBody,
  8. RouteShorthandOptions,
  9. } from 'fastify'
  10. import { Server, IncomingMessage, ServerResponse } from 'http'
  11. import { MEDIA_PARTITION_KEY } from '../../constants'
  12. import { errorSchema } from '../../schemas'
  13. import { containerFor, getItem } from '../../lib/database'
  14. import { badRequestError, serverError } from '../../lib/errors'
  15. import { deleteMedia, generateSAS, getBlobUrl } from '../../lib/media'
  16. import { createId } from '../../lib/utils'
  17. import { Media } from '../../types/collections'
  18. import { PluginOptions } from '../../types'
  19. function getSASRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
  20. const options: RouteShorthandOptions = {
  21. schema: {
  22. description: 'Get a shared access signature.',
  23. tags: ['media'],
  24. response: {
  25. 200: {
  26. type: 'object',
  27. properties: {
  28. sas: { type: 'string' },
  29. blobUrl: { type: 'string' },
  30. id: { type: 'string' },
  31. },
  32. },
  33. },
  34. },
  35. }
  36. server.get<DefaultQuery, DefaultParams, DefaultHeaders, DefaultBody>('/v1/sas', options, async () => {
  37. return {
  38. sas: generateSAS('arcw', 5),
  39. blobUrl: getBlobUrl(),
  40. id: createId(),
  41. }
  42. })
  43. }
  44. function addRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
  45. interface Body {
  46. name: string
  47. size: number
  48. type: string
  49. originalName: string
  50. }
  51. const options: RouteShorthandOptions = {
  52. schema: {
  53. description: 'Create a Media item.',
  54. tags: ['media'],
  55. body: {
  56. type: 'object',
  57. required: ['name', 'size', 'type', 'originalName'],
  58. properties: {
  59. name: { type: 'string' },
  60. size: { type: 'number' },
  61. type: { type: 'string' },
  62. originalName: { type: 'string' },
  63. },
  64. },
  65. response: {
  66. 204: {
  67. description: 'Media item created.',
  68. type: 'object',
  69. },
  70. 400: errorSchema,
  71. },
  72. },
  73. }
  74. server.post<DefaultQuery, DefaultParams, DefaultHeaders, Body>('/v1/media', options, async (request, reply) => {
  75. if (!server.database) return serverError(reply)
  76. const { name, size, type, originalName } = request.body
  77. const container = containerFor(server.database.client, 'Media')
  78. const item = await getItem<Media>({
  79. container,
  80. id: name,
  81. partitionKey: MEDIA_PARTITION_KEY,
  82. })
  83. reply.code(204)
  84. if (item) return
  85. await container.items.create<Media>({
  86. id: name,
  87. pk: MEDIA_PARTITION_KEY,
  88. size,
  89. type,
  90. originalName,
  91. attached: false,
  92. created: Date.now(),
  93. })
  94. })
  95. }
  96. function deleteRoute(server: FastifyInstance<Server, IncomingMessage, ServerResponse>) {
  97. interface Params {
  98. name: string
  99. }
  100. const options: RouteShorthandOptions = {
  101. schema: {
  102. description: 'Delete a media item.',
  103. tags: ['media'],
  104. querystring: {
  105. type: 'object',
  106. required: ['name'],
  107. properties: {
  108. name: { type: 'string' },
  109. },
  110. },
  111. response: {
  112. 204: {
  113. description: 'Media item deleted.',
  114. type: 'object',
  115. },
  116. 400: errorSchema,
  117. },
  118. },
  119. }
  120. server.delete<DefaultQuery, Params, DefaultHeaders, DefaultBody>('/v1/media', options, async (request, reply) => {
  121. if (!server.database) return serverError(reply)
  122. const mediaItem = containerFor(server.database.client, 'Media').item(request.query.name, MEDIA_PARTITION_KEY)
  123. const { resource: media } = await mediaItem.read<Media>()
  124. if (!media) return badRequestError(reply)
  125. reply.code(204)
  126. if (media.attached) return
  127. await mediaItem.delete()
  128. await deleteMedia(request.body.name)
  129. })
  130. }
  131. const plugin: Plugin<Server, IncomingMessage, ServerResponse, PluginOptions> = async server => {
  132. getSASRoute(server)
  133. addRoute(server)
  134. deleteRoute(server)
  135. }
  136. export default plugin