Quick hack: Redirect to asset by URL - Endpoint extension for directus.io
October 21, 2021 ยท View on GitHub
// Quick hack: Redirect to asset by URL - Endpoint extension for directus.io // ========================================================================= // // 2021 - ToJans - Public Domain // // *** Don't hold me liable if it breaks anything! Quick hack, might expose all your data! // // You can use this endpoint extension to access assets via the folder and file structure // you used in the file module, so you don't need to reference assets by guid anymore. // // Usage: // ------ // // Browse to "/filestorage/[folder/subfolder/filename.ext]" according to the [folder]s // and [filename_download] you used in the file module. It will redirect to "/assets/some-huge-guid-xxxxx" // // Installation: // ------------- // // Save the contents of this file in "$DIRECTUS_ROOT/extensions/endpoints/filestorage/index.js" and (re)start directus. // // Note: // ----- // This is just a quick hack to see how extensible directus.io is, and I have to say I'm not disappointed. // // However, I only discovered directus.io a couple of hours ago, so I'm by no means an expert on this stuff. // So authorization & async might need to be validated TBH.
module.exports = function registerEndpoint(router, context) { const { services, exceptions, } = context;
const {
FilesService,
FoldersService,
} = services;
const {
ServiceUnavailableException
} = exceptions;
router.get('*', (req, res, next) => {
const foldersService = new FoldersService({
schema: req.schema,
accountability: req.accountability
});
const paths = req.params[0].split("/").filter(x => !!x);
const file = paths.pop();
let parentKey = null;
let currentPath = "/";
let hasError = false;
foldersService.readByQuery({
filter: {
name: {
"_in": paths
}
},
fields: ["id", "name", "parent"]
}).then(folders => {
while (paths.length && !hasError) {
head = paths.shift();
currentPath += head;
let headFolder = folders.find(x => x.parent == parentKey && x.name == head);
if (!headFolder) {
res.status(404).send({
status: 404,
error: "path not found: " + currentPath
});
hasError = true;
break;
}
parentKey = headFolder.id;
}
// TODO: I should handle this properly
if (!hasError) {
const filesService = new FilesService({
schema: req.schema,
accountability: req.accountability
});
return filesService.readByQuery({
filter: {
"filename_download": {
"_eq": file
},
// TODO:
// This does not seem to work, as it fails on null values, so for now I just check it manually
// This might cause perf issues if we have a lot of files with the same name....
// "folder": {
// "_eq": parentKey
// }
},
fields: ["id", "type", "folder"]
});
}
})
.then((results) => {
// TODO: workaround I mentioned a few lines earlier
results = results.filter(x => x.folder === parentKey);
if (!results.length) {
res.status(404).send({
status: 404,
error: "file not found"
});
} else {
res.redirect("/assets/" + results[0].id);
}
})
.catch((error) => {
return next(new ServiceUnavailableException(error.message));
});
});
};