The Haplo Platform provides a file store, which is integrated into the other parts of the API.
Files are addressed by their SHA256 cryptographic digest and file size. As the chance of a digest collision is minimal, digest based addressing allows unambiguous references to files throughout the API along with built in assurances of file integrity.
Files can be generated and transformed using the file transform pipeline API.
While the underlying file store does not have a concept of versions of a file, the user interface uses the
trackingId property of the
FileIdentifier to identify a ‘file version track’ through the previous versions of a
logMessage properties are then used to display version numbers and change logs to the user.
When forms are rendered, a thumbnail and filename will be displayed, linked to a download URL which includes an authentication token.
as:"file" argument on a request handler, and receive a
BinaryData argument on your request handler function. But it’s probably more convenient and a better user experience to use the forms system.
"file" type field in your database tables.
It’s important that 1) users can only download files they’re permitted to see, and 2) permission to download a file can be revoked. Therefore, knowledge of a digest is not sufficient to be able to download a file.
The platform will allow a user to download a file if either:
- an object can be found which includes a
FileIdentifierfor the file, and the user is permitted to read it, or
- the download URL includes an authentication signature tied to the user’s current session.
All that’s left is to make sure that the user can’t add a
FileIdentifier for a file they want to an object they can read, or insert a digest into some other database which gives them permission.
Your code should be carefully written so it does not accidentally give access to a file. Unlike the object store, it’s not possible for the platform to automatically enforce permissions as file handling can be used in so many ways.
The platform provides a per-file secret which can only be generated by the server. If you are sending a digest to a client and then storing it again when submitted by the user, then you should also send the secret and use the
checkSecret() function to check the value which is returned. (The other way a user can prove they have access to a file is to upload it, so the
BinaryData object, used for file uploads, doesn’t need a secret.)
The object editor and the forms system handle these secrets for you, so use them whenever practical.