Last active
October 9, 2024 03:41
-
-
Save ToJans/fa18e2a7363edd24be6ad8dda2dd0232 to your computer and use it in GitHub Desktop.
Quick hack: Redirect to asset by URL - Endpoint extension for directus.io
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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)); | |
}); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment