mirror of
https://github.com/aljazceru/landscape-template.git
synced 2025-12-18 14:54:23 +01:00
feat: add function to get unique upload url add HostedImage table
This commit is contained in:
35
api/functions/services/imageUpload.service.js
Normal file
35
api/functions/services/imageUpload.service.js
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
const { CONSTS } = require('../../utils')
|
||||||
|
const axios = require('axios')
|
||||||
|
const FormData = require('form-data')
|
||||||
|
|
||||||
|
const BASE_URL = 'https://api.cloudflare.com/client/v4'
|
||||||
|
|
||||||
|
const operationUrls = {
|
||||||
|
'image.uploadUrl': `${BASE_URL}/accounts/${CONSTS.CLOUDFLARE_IMAGE_ACCOUNT_ID}/images/v2/direct_upload`,
|
||||||
|
}
|
||||||
|
|
||||||
|
async function getDirectUploadUrl() {
|
||||||
|
const url = operationUrls['image.uploadUrl']
|
||||||
|
|
||||||
|
const formData = new FormData()
|
||||||
|
formData.append('requireSignedURLs', 'false')
|
||||||
|
|
||||||
|
const config = {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${CONSTS.CLOUDFLARE_IMAGE_API_KEY}`,
|
||||||
|
...formData.getHeaders(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await axios.post(url, formData, config)
|
||||||
|
|
||||||
|
if (!result.data.success) {
|
||||||
|
throw new Error(result.data, { cause: error })
|
||||||
|
}
|
||||||
|
|
||||||
|
return result.data.result
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = {
|
||||||
|
getDirectUploadUrl,
|
||||||
|
}
|
||||||
46
api/functions/upload-image-url/upload-image-url.js
Normal file
46
api/functions/upload-image-url/upload-image-url.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
const serverless = require('serverless-http')
|
||||||
|
const { createExpressApp } = require('../../modules')
|
||||||
|
const express = require('express')
|
||||||
|
const extractKeyFromCookie = require('../../utils/extractKeyFromCookie')
|
||||||
|
const { getUserByPubKey } = require('../../auth/utils/helperFuncs')
|
||||||
|
const { getDirectUploadUrl } = require('../services/imageUpload.service')
|
||||||
|
const { prisma } = require('../../prisma')
|
||||||
|
|
||||||
|
const postUploadImageUrl = async (req, res) => {
|
||||||
|
const userPubKey = await extractKeyFromCookie(req.headers.cookie ?? req.headers.Cookie)
|
||||||
|
const user = await getUserByPubKey(userPubKey)
|
||||||
|
|
||||||
|
if (!user) return res.status(401).json({ status: 'ERROR', reason: 'Not Authenticated' })
|
||||||
|
|
||||||
|
const { filename } = req.body
|
||||||
|
|
||||||
|
if (!filename) return res.status(422).json({ status: 'ERROR', reason: "The field 'filename' is required`" })
|
||||||
|
|
||||||
|
try {
|
||||||
|
const uploadUrl = await getDirectUploadUrl()
|
||||||
|
|
||||||
|
await prisma.hostedImage.create({
|
||||||
|
data: { id: uploadUrl.id, filename },
|
||||||
|
})
|
||||||
|
|
||||||
|
return res.status(200).json(uploadUrl)
|
||||||
|
} catch (error) {
|
||||||
|
res.status(500).send('Unexpected error happened, please try again')
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let app
|
||||||
|
|
||||||
|
if (process.env.LOCAL) {
|
||||||
|
app = createExpressApp()
|
||||||
|
app.post('/upload-image-url', postUploadImageUrl)
|
||||||
|
} else {
|
||||||
|
const router = express.Router()
|
||||||
|
router.post('/upload-image-url', postUploadImageUrl)
|
||||||
|
app = createExpressApp(router)
|
||||||
|
}
|
||||||
|
|
||||||
|
const handler = serverless(app)
|
||||||
|
exports.handler = async (event, context) => {
|
||||||
|
return await handler(event, context)
|
||||||
|
}
|
||||||
@@ -1,11 +1,15 @@
|
|||||||
const BOLT_FUN_LIGHTNING_ADDRESS = 'johns@getalby.com'; // #TODO, replace it by bolt-fun lightning address if there exist one
|
const BOLT_FUN_LIGHTNING_ADDRESS = 'johns@getalby.com' // #TODO, replace it by bolt-fun lightning address if there exist one
|
||||||
const JWT_SECRET = process.env.JWT_SECRET;
|
const JWT_SECRET = process.env.JWT_SECRET
|
||||||
const LNURL_AUTH_HOST = process.env.LNURL_AUTH_HOST
|
const LNURL_AUTH_HOST = process.env.LNURL_AUTH_HOST
|
||||||
|
const CLOUDFLARE_IMAGE_ACCOUNT_ID = process.env.CLOUDFLARE_IMAGE_ACCOUNT_ID
|
||||||
|
const CLOUDFLARE_IMAGE_API_KEY = process.env.CLOUDFLARE_IMAGE_API_KEY
|
||||||
|
|
||||||
const CONSTS = {
|
const CONSTS = {
|
||||||
JWT_SECRET,
|
JWT_SECRET,
|
||||||
BOLT_FUN_LIGHTNING_ADDRESS,
|
BOLT_FUN_LIGHTNING_ADDRESS,
|
||||||
LNURL_AUTH_HOST,
|
LNURL_AUTH_HOST,
|
||||||
|
CLOUDFLARE_IMAGE_ACCOUNT_ID,
|
||||||
|
CLOUDFLARE_IMAGE_API_KEY,
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = CONSTS;
|
module.exports = CONSTS
|
||||||
|
|||||||
5703
package-lock.json
generated
5703
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -41,6 +41,7 @@
|
|||||||
"env-cmd": "^10.1.0",
|
"env-cmd": "^10.1.0",
|
||||||
"express": "^4.18.1",
|
"express": "^4.18.1",
|
||||||
"express-session": "^1.17.3",
|
"express-session": "^1.17.3",
|
||||||
|
"form-data": "^4.0.0",
|
||||||
"framer-motion": "^6.3.0",
|
"framer-motion": "^6.3.0",
|
||||||
"fslightbox-react": "^1.6.2-2",
|
"fslightbox-react": "^1.6.2-2",
|
||||||
"graphql": "^16.3.0",
|
"graphql": "^16.3.0",
|
||||||
@@ -179,6 +180,7 @@
|
|||||||
"netlify-cli": "^10.0.0",
|
"netlify-cli": "^10.0.0",
|
||||||
"postcss": "^8.4.12",
|
"postcss": "^8.4.12",
|
||||||
"readable-stream": "^4.1.0",
|
"readable-stream": "^4.1.0",
|
||||||
|
"serverless": "^3.22.0",
|
||||||
"serverless-offline": "^8.7.0",
|
"serverless-offline": "^8.7.0",
|
||||||
"tailwindcss": "^3.0.24",
|
"tailwindcss": "^3.0.24",
|
||||||
"webpack": "^5.72.0"
|
"webpack": "^5.72.0"
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
-- CreateTable
|
||||||
|
CREATE TABLE "HostedImage" (
|
||||||
|
"id" TEXT NOT NULL,
|
||||||
|
"filename" TEXT NOT NULL,
|
||||||
|
"createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||||
|
"is_used" BOOLEAN NOT NULL DEFAULT false,
|
||||||
|
|
||||||
|
CONSTRAINT "HostedImage_pkey" PRIMARY KEY ("id")
|
||||||
|
);
|
||||||
@@ -221,3 +221,13 @@ model GeneratedK1 {
|
|||||||
sid String?
|
sid String?
|
||||||
createdAt DateTime @default(now())
|
createdAt DateTime @default(now())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// -----------------
|
||||||
|
// Hosted Image
|
||||||
|
// -----------------
|
||||||
|
model HostedImage {
|
||||||
|
id String @id
|
||||||
|
filename String
|
||||||
|
createdAt DateTime @default(now())
|
||||||
|
is_used Boolean @default(false)
|
||||||
|
}
|
||||||
|
|||||||
@@ -76,3 +76,10 @@ functions:
|
|||||||
- http:
|
- http:
|
||||||
path: pubkeys-to-users
|
path: pubkeys-to-users
|
||||||
method: post
|
method: post
|
||||||
|
|
||||||
|
upload-image-url:
|
||||||
|
handler: api/functions/upload-image-url/upload-image-url.handler
|
||||||
|
events:
|
||||||
|
- http:
|
||||||
|
path: upload-image-url
|
||||||
|
method: post
|
||||||
|
|||||||
Reference in New Issue
Block a user