mirror of
https://github.com/directus/directus.git
synced 2026-01-28 16:48:02 -05:00
Allow custom transformations of assets (#6593)
* Allow custom transformations of assets This exposes one query parameter `transforms`, which is a JSON array of shard transformation operations. It also updates the asset presets. The UX for this still needs some work * Rename options to arguments for presets More explicit * options -> arguments in setting spec * Better errors for invalid JSON in asset presets * Add limit to transforms query parameter * Use flattened option for extra transforms * Fix placeholder color of code input * Allow "simple mode" aliases * Add documentation Co-authored-by: rijkvanzanten <rijkvanzanten@me.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import { ForbiddenException, InvalidQueryException, RangeNotSatisfiableException
|
||||
import useCollection from '../middleware/use-collection';
|
||||
import { AssetsService, PayloadService } from '../services';
|
||||
import storage from '../storage';
|
||||
import { Transformation } from '../types/assets';
|
||||
import { TransformationParams, TransformationMethods, TransformationPreset } from '../types/assets';
|
||||
import asyncHandler from '../utils/async-handler';
|
||||
|
||||
const router = Router();
|
||||
@@ -68,26 +68,63 @@ router.get(
|
||||
if ('key' in transformation && Object.keys(transformation).length > 1) {
|
||||
throw new InvalidQueryException(`You can't combine the "key" query parameter with any other transformation.`);
|
||||
}
|
||||
if ('quality' in transformation && (Number(transformation.quality) < 1 || Number(transformation.quality) > 100)) {
|
||||
throw new InvalidQueryException(`"quality" Parameter has to between 1 to 100`);
|
||||
|
||||
if ('transforms' in transformation) {
|
||||
let transforms: unknown;
|
||||
|
||||
// Try parse the JSON array
|
||||
try {
|
||||
transforms = JSON.parse(transformation['transforms'] as string);
|
||||
} catch {
|
||||
throw new InvalidQueryException(`"transforms" Parameter needs to be a JSON array of allowed transformations.`);
|
||||
}
|
||||
|
||||
// Check if it is actually an array.
|
||||
if (!Array.isArray(transforms)) {
|
||||
throw new InvalidQueryException(`"transforms" Parameter needs to be a JSON array of allowed transformations.`);
|
||||
}
|
||||
|
||||
// Check against ASSETS_TRANSFORM_MAX_OPERATIONS
|
||||
if (transforms.length > Number(env.ASSETS_TRANSFORM_MAX_OPERATIONS)) {
|
||||
throw new InvalidQueryException(
|
||||
`"transforms" Parameter is only allowed ${env.ASSETS_TRANSFORM_MAX_OPERATIONS} transformations.`
|
||||
);
|
||||
}
|
||||
|
||||
// Check the transformations are valid
|
||||
transforms.forEach((transform) => {
|
||||
const name = transform[0];
|
||||
|
||||
if (!TransformationMethods.includes(name)) {
|
||||
throw new InvalidQueryException(`"transforms" Parameter does not allow "${name}" as a transformation.`);
|
||||
}
|
||||
});
|
||||
|
||||
transformation.transforms = transforms;
|
||||
}
|
||||
|
||||
const systemKeys = SYSTEM_ASSET_ALLOW_LIST.map((transformation) => transformation.key);
|
||||
const systemKeys = SYSTEM_ASSET_ALLOW_LIST.map((transformation) => transformation.key!);
|
||||
const allKeys: string[] = [
|
||||
...systemKeys,
|
||||
...(assetSettings.storage_asset_presets || []).map((transformation: Transformation) => transformation.key),
|
||||
...(assetSettings.storage_asset_presets || []).map((transformation: TransformationParams) => transformation.key),
|
||||
];
|
||||
|
||||
// For use in the next request handler
|
||||
res.locals.shortcuts = [...SYSTEM_ASSET_ALLOW_LIST, ...(assetSettings.storage_asset_presets || [])];
|
||||
res.locals.transformation = transformation;
|
||||
|
||||
if (Object.keys(transformation).length === 0) {
|
||||
if (
|
||||
Object.keys(transformation).length === 0 ||
|
||||
('transforms' in transformation && transformation.transforms!.length === 0)
|
||||
) {
|
||||
return next();
|
||||
}
|
||||
|
||||
if (assetSettings.storage_asset_transform === 'all') {
|
||||
if (transformation.key && allKeys.includes(transformation.key as string) === false)
|
||||
if (transformation.key && allKeys.includes(transformation.key as string) === false) {
|
||||
throw new InvalidQueryException(`Key "${transformation.key}" isn't configured.`);
|
||||
}
|
||||
|
||||
return next();
|
||||
} else if (assetSettings.storage_asset_transform === 'presets') {
|
||||
if (allKeys.includes(transformation.key as string)) return next();
|
||||
@@ -107,9 +144,9 @@ router.get(
|
||||
schema: req.schema,
|
||||
});
|
||||
|
||||
const transformation: Transformation = res.locals.transformation.key
|
||||
? res.locals.shortcuts.find(
|
||||
(transformation: Transformation) => transformation.key === res.locals.transformation.key
|
||||
const transformation: TransformationParams | TransformationPreset = res.locals.transformation.key
|
||||
? (res.locals.shortcuts as TransformationPreset[]).find(
|
||||
(transformation) => transformation.key === res.locals.transformation.key
|
||||
)
|
||||
: res.locals.transformation;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user