feat(server): remove old /admin/uploads, validate isResized on product endpoints
This commit is contained in:
+1
-1
@@ -42,7 +42,7 @@ await fastify.register(jwt, {
|
||||
await fastify.register(multipart, {
|
||||
limits: {
|
||||
files: 10,
|
||||
/** Совпадает с лимитом одного файла для `POST /api/admin/uploads` (товары, галерея). */
|
||||
/** Совпадает с лимитом одного файла для `POST /api/admin/gallery/upload` (галерея). */
|
||||
fileSize: getProductImageMaxFileBytes(),
|
||||
},
|
||||
})
|
||||
|
||||
@@ -1,11 +1,4 @@
|
||||
import { upsertGalleryImagesByUrls } from '../../lib/gallery.js'
|
||||
import { prisma } from '../../lib/prisma.js'
|
||||
import {
|
||||
formatFileTooLargeMessage,
|
||||
getProductImageMaxFileBytes,
|
||||
isMultipartFileTooLargeError,
|
||||
} from '../../lib/upload-limits.js'
|
||||
import { persistMultipartImages } from '../../lib/upload-images.js'
|
||||
|
||||
const CREATE_PRODUCT_SCHEMA = {
|
||||
body: {
|
||||
@@ -59,33 +52,6 @@ export async function registerAdminProductRoutes(fastify) {
|
||||
},
|
||||
)
|
||||
|
||||
fastify.post(
|
||||
'/api/admin/uploads',
|
||||
{ preHandler: [fastify.verifyAdmin] },
|
||||
async (request, reply) => {
|
||||
try {
|
||||
const urls = await persistMultipartImages(request, {
|
||||
maxFiles: 10,
|
||||
maxFileBytes: getProductImageMaxFileBytes(),
|
||||
eager: true,
|
||||
})
|
||||
await upsertGalleryImagesByUrls(urls)
|
||||
return { urls }
|
||||
} catch (error) {
|
||||
let message = error instanceof Error ? error.message : 'Не удалось загрузить файлы'
|
||||
let statusCode =
|
||||
error && typeof error === 'object' && 'statusCode' in error && Number.isInteger(error.statusCode)
|
||||
? Number(error.statusCode)
|
||||
: 400
|
||||
if (isMultipartFileTooLargeError(error)) {
|
||||
message = formatFileTooLargeMessage(getProductImageMaxFileBytes())
|
||||
statusCode = 413
|
||||
}
|
||||
return reply.code(statusCode).send({ error: message })
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
fastify.post(
|
||||
'/api/admin/products',
|
||||
{ preHandler: [fastify.verifyAdmin], schema: CREATE_PRODUCT_SCHEMA },
|
||||
@@ -122,6 +88,25 @@ export async function registerAdminProductRoutes(fastify) {
|
||||
return
|
||||
}
|
||||
|
||||
if (Array.isArray(body.imageUrls) && body.imageUrls.length > 0) {
|
||||
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
||||
if (urls.length > 0) {
|
||||
const galleryImages = await prisma.galleryImage.findMany({
|
||||
where: { url: { in: urls } },
|
||||
select: { url: true, isResized: true },
|
||||
})
|
||||
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
|
||||
const notFound = urls.filter((u) => !galleryMap.has(u))
|
||||
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
|
||||
if (notFound.length > 0) {
|
||||
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
|
||||
}
|
||||
if (notResized.length > 0) {
|
||||
return reply.code(400).send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const n = Number(body.quantity)
|
||||
if (!Number.isInteger(n) || n < 0 || n > 10) {
|
||||
reply.code(400).send({ error: 'Количество — целое число от 0 до 10' })
|
||||
@@ -228,6 +213,25 @@ export async function registerAdminProductRoutes(fastify) {
|
||||
data.categoryId = cid
|
||||
}
|
||||
|
||||
if (body.imageUrls !== undefined && Array.isArray(body.imageUrls)) {
|
||||
const urls = body.imageUrls.map((u) => String(u || '').trim()).filter(Boolean)
|
||||
if (urls.length > 0) {
|
||||
const galleryImages = await prisma.galleryImage.findMany({
|
||||
where: { url: { in: urls } },
|
||||
select: { url: true, isResized: true },
|
||||
})
|
||||
const galleryMap = new Map(galleryImages.map((g) => [g.url, g]))
|
||||
const notFound = urls.filter((u) => !galleryMap.has(u))
|
||||
const notResized = urls.filter((u) => galleryMap.get(u) && !galleryMap.get(u).isResized)
|
||||
if (notFound.length > 0) {
|
||||
return reply.code(400).send({ error: 'Некоторые изображения не найдены в галерее' })
|
||||
}
|
||||
if (notResized.length > 0) {
|
||||
return reply.code(400).send({ error: 'Изображения должны быть обработаны (resize) перед прикреплением к товару' })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const imagesUpdate =
|
||||
body.imageUrls !== undefined
|
||||
? {
|
||||
|
||||
Reference in New Issue
Block a user