This commit is contained in:
@@ -42,4 +42,17 @@ export function validateImageSignature(data, mimeType) {
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
export function validateImageSortOrder(sortOrder) {
|
||||
if (!Number.isInteger(sortOrder) || sortOrder < 0 || sortOrder > 2147483647) {
|
||||
throw createApplicationError('IMAGE_ORDER_INVALID', 'Image order must be an integer between 0 and 2147483647.', 400);
|
||||
}
|
||||
}
|
||||
|
||||
export function normalizeImageAltText(altText) {
|
||||
if (altText === null) return null;
|
||||
if (typeof altText !== 'string' || altText.trim().length > 1000) {
|
||||
throw createApplicationError('IMAGE_ALT_TEXT_INVALID', 'Alt text must be text up to 1,000 characters or null.', 400);
|
||||
}
|
||||
return altText.trim();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { toAdminInventoryImageDto } from '@pokemon-inventory/contracts/image';
|
||||
import { createInventoryImageSchema, moveInventoryImageSchema } from '@pokemon-inventory/validation/image';
|
||||
import { createInventoryImageSchema, moveInventoryImageSchema, updateImageOrderSchema, updateImageAltTextSchema } from '@pokemon-inventory/validation/image';
|
||||
import { randomUUID } from 'node:crypto';
|
||||
|
||||
import { createApplicationError } from '../../../shared/errors/application-error.js';
|
||||
@@ -110,11 +110,13 @@ export async function registerAdminImageRoutes(app, options) {
|
||||
return { data: toAdminInventoryImageDto(image) };
|
||||
});
|
||||
|
||||
app.patch('/images/:id/order', async (request) => {
|
||||
app.patch('/images/:id/order', async (request, reply) => {
|
||||
const admin = await authorizeAdminMutation(request);
|
||||
const result = updateImageOrderSchema.safeParse(request.body);
|
||||
if (!result.success) return validationError(reply, result);
|
||||
const image = await inventoryImageService.updateOrder({
|
||||
imageId: request.params.id,
|
||||
sortOrder: request.body?.sortOrder,
|
||||
sortOrder: result.data.sortOrder,
|
||||
sellerId: admin.sellerId,
|
||||
});
|
||||
return { data: toAdminInventoryImageDto(image) };
|
||||
@@ -129,11 +131,13 @@ export async function registerAdminImageRoutes(app, options) {
|
||||
return { data: toAdminInventoryImageDto(image) };
|
||||
});
|
||||
|
||||
app.patch('/images/:id/alt-text', async (request) => {
|
||||
app.patch('/images/:id/alt-text', async (request, reply) => {
|
||||
const admin = await authorizeAdminMutation(request);
|
||||
const result = updateImageAltTextSchema.safeParse(request.body);
|
||||
if (!result.success) return validationError(reply, result);
|
||||
const image = await inventoryImageService.updateAltText({
|
||||
imageId: request.params.id,
|
||||
altText: request.body?.altText ?? null,
|
||||
altText: result.data.altText,
|
||||
sellerId: admin.sellerId,
|
||||
});
|
||||
return { data: toAdminInventoryImageDto(image) };
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { validateImageMove } from '../domain/image-order.js';
|
||||
import { createApplicationError } from '../../../shared/errors/application-error.js';
|
||||
import { validateImageSignature, validateInventoryImageMetadata } from '../domain/inventory-image.js';
|
||||
import { normalizeImageAltText, validateImageSortOrder, validateImageSignature, validateInventoryImageMetadata } from '../domain/inventory-image.js';
|
||||
|
||||
export function createInventoryImageService({ inventoryImageRepository, imageDerivativeJobRepository, imageStorage }) {
|
||||
return {
|
||||
@@ -49,6 +49,7 @@ export function createInventoryImageService({ inventoryImageRepository, imageDer
|
||||
},
|
||||
|
||||
async updateOrder({ imageId, sortOrder, sellerId }) {
|
||||
validateImageSortOrder(sortOrder);
|
||||
return requireOwnedImage(inventoryImageRepository.updateOrderForSeller(imageId, sortOrder, sellerId));
|
||||
},
|
||||
|
||||
@@ -57,7 +58,7 @@ export function createInventoryImageService({ inventoryImageRepository, imageDer
|
||||
},
|
||||
|
||||
async updateAltText({ imageId, altText, sellerId }) {
|
||||
return requireOwnedImage(inventoryImageRepository.updateAltTextForSeller(imageId, altText, sellerId));
|
||||
return requireOwnedImage(inventoryImageRepository.updateAltTextForSeller(imageId, normalizeImageAltText(altText), sellerId));
|
||||
},
|
||||
|
||||
async delete({ imageId, sellerId }) {
|
||||
|
||||
Reference in New Issue
Block a user