fix: file upload and OAuth2 (#10)

This commit is contained in:
Divlo
2022-04-08 21:36:29 +02:00
committed by GitHub
parent 69c567cb66
commit a4c77fec50
30 changed files with 529 additions and 366 deletions

View File

@ -7,6 +7,10 @@ dotenv.config()
export const PORT = parseInt(process.env.PORT ?? '8080', 10)
export const HOST = process.env.HOST ?? '0.0.0.0'
export const API_URL = process.env.API_URL ?? `http://${HOST}:${PORT}`
export const FILE_UPLOADS_API_URL =
process.env.FILE_UPLOADS_API_URL ?? 'http://localhost:8000'
export const FILE_UPLOADS_API_KEY =
process.env.FILE_UPLOADS_API_KEY ?? 'apiKeySecret'
export const JWT_ACCESS_SECRET =
process.env.JWT_ACCESS_SECRET ?? 'accessTokenSecret'
export const JWT_REFRESH_SECRET =
@ -19,17 +23,3 @@ export const ROOT_URL = new URL('../', SRC_URL)
export const EMAIL_URL = new URL('./email/', ROOT_URL)
export const EMAIL_TEMPLATE_URL = new URL('./email-template.ejs', EMAIL_URL)
export const EMAIL_LOCALES_URL = new URL('./locales/', EMAIL_URL)
export const UPLOADS_URL = new URL('./uploads/', ROOT_URL)
export const SUPPORTED_IMAGE_MIMETYPE = [
'image/png',
'image/jpg',
'image/jpeg',
'image/gif'
]
/** in megabytes */
export const MAXIMUM_IMAGE_SIZE = 10
/** in megabytes */
export const MAXIMUM_FILE_SIZE = 100

View File

@ -10,7 +10,7 @@ export const swaggerOptions: FastifyDynamicSwaggerOptions = {
routePrefix: '/documentation',
openapi: {
info: {
title: 'Thream',
title: packageJSON.name,
description: packageJSON.description,
version: packageJSON.version
},

View File

@ -1,21 +1,29 @@
import fs from 'node:fs'
import { URL } from 'node:url'
import { randomUUID } from 'node:crypto'
import axios from 'axios'
import FormData from 'form-data'
import { FastifyInstance, FastifyRequest } from 'fastify'
import { Multipart } from 'fastify-multipart'
import { ROOT_URL } from '../configurations/index.js'
import {
FILE_UPLOADS_API_KEY,
FILE_UPLOADS_API_URL
} from '../configurations/index.js'
export const fileUploadAPI = axios.create({
baseURL: FILE_UPLOADS_API_URL,
headers: {
'Content-Type': 'application/json'
}
})
/** in megabytes */
export const MAXIMUM_FILE_SIZE = 100
export interface UploadFileOptions {
folderInUploadsFolder: 'guilds' | 'messages' | 'users'
request: FastifyRequest
fastify: FastifyInstance
/** in megabytes */
maximumFileSize: number
supportedFileMimetype?: string[]
}
export interface UploadFileResult {
@ -26,43 +34,42 @@ export interface UploadFileResult {
export const uploadFile = async (
options: UploadFileOptions
): Promise<UploadFileResult> => {
const {
fastify,
request,
folderInUploadsFolder,
maximumFileSize,
supportedFileMimetype
} = options
const { fastify, request, folderInUploadsFolder } = options
let files: Multipart[] = []
try {
files = await request.saveRequestFiles({
limits: {
files: 1,
fileSize: maximumFileSize * 1024 * 1024
fileSize: MAXIMUM_FILE_SIZE * 1024 * 1024
}
})
} catch (error) {
throw fastify.httpErrors.requestHeaderFieldsTooLarge(
`File should be less than ${maximumFileSize}mb.`
`File should be less than ${MAXIMUM_FILE_SIZE}mb.`
)
}
if (files.length !== 1) {
throw fastify.httpErrors.badRequest('You must upload at most one file.')
}
const file = files[0]
if (
supportedFileMimetype != null &&
!supportedFileMimetype.includes(file.mimetype)
) {
throw fastify.httpErrors.badRequest(
`The file must have a valid type (${supportedFileMimetype.join(', ')}).`
const formData = new FormData()
formData.append('file', fs.createReadStream(file.filepath))
try {
const response = await fileUploadAPI.post(
`/uploads/${folderInUploadsFolder}`,
formData,
{
headers: {
'X-API-Key': FILE_UPLOADS_API_KEY,
...formData.getHeaders()
}
}
)
return { pathToStoreInDatabase: response.data, mimetype: file.mimetype }
} catch (error: any) {
throw fastify.httpErrors.createError(
error.response.data.statusCode,
error.response.data.message
)
}
const splitedMimetype = file.mimetype.split('/')
const fileExtension = splitedMimetype[1]
const filePath = `uploads/${folderInUploadsFolder}/${randomUUID()}.${fileExtension}`
const fileURL = new URL(filePath, ROOT_URL)
const pathToStoreInDatabase = `/${filePath}`
await fs.promises.copyFile(file.filepath, fileURL)
return { pathToStoreInDatabase, mimetype: file.mimetype }
}