Files
swisssign-challenge/README.md
2025-01-31 16:56:25 +01:00

103 lines
4.0 KiB
Markdown

# SwisssignChallenge
## Requirements
- [GraalVM 23](https://www.graalvm.org/)
- PostgreSQL 17, but a Docker Compose file is available for your convenience.
If you decide to run it locally, **please check application.yml for default values**.
## Generate sources
To generate code from the API contract, run `./mvnw generate-sources`
## Build native executable
1. Make sure your `JAVA_HOME` or `GRAALVM_HOME` environment variable is correctly
pointing to your JDK.
1. Run `./mvnw -Pnative native:compile`.
Note that you don't need to build a native executable to run a development
environment.
## Retrieving PDFs
You must have 2 PDF files with the names `cv-actual.pdf` and `cv-stackoverflow.pdf`
as this is what is referenced by the rows in the database. By default, they must
be placed in `/srv/pdfs/` but feel free to modify the constant before running the
code.
For your convenience, those files are placed at the root of the project.
## Choices
### GraalVM
It's my first time using GraalVM, but I took the opportunity of using it in this
project because of its small scale. Its goals are to improve the performance of
JVM-based applications to match native languages.
Startup times are also greatly improved; less than 0.5 seconds. The drawback is
that the build times are greatly lengthened; around 1 minute for an empty
project.
### PostgreSQL
I don't think I have to explain much about PostgreSQL, but it's well-suited for
both small and large-scale projects. Also, support with Spring Boot is, in my
experience, flawless.
### Flyway
I'm experienced with Liquibase, but after quickly reading about errors related
to GraalVM, I understood it was unsupported. Flyway is another popular migration
tool, so I gave it a go. I have nothing to say for or against it.
### JWT
I knew the basics but never implemented the authentication layer myself. JWT
is a standard, but in an enterprise environment there would probably be an
OIDC-compliant service to be plugged into.
After initializing the correct beans, it worked really well.
As I don't specify the JWT secret, all issued tokens are not recognized after
a restart and must be regenerated (i.e. all users are logged out).
LLMs were a great help here too, along with good ol' Baeldung.
### Files
At first, I wanted to store the files as a BYTEA in the database. I thought
this would be much simpler and minimalistic, but I was wrong on the first point.
I gave up after I couldn't find the root of the error "cannot convert to long",
despite not having a single long in my source code. Anyway, files are stored
on the filesystem and are retrieved by the `PdfServiceImpl`. This service makes
sure that the file name doesn't contain `".."` in the file name in order to
prevent [directory traversal attacks](https://en.wikipedia.org/wiki/Directory_traversal_attack).
Files are not uploaded by the user so there is virtually 0 chance of it containing
malicious characters, but I thought it was important to safeguard against this.
### UUID
As there is insanely little chance of collision, UUID are most useful in
distributed systems where we could give the responsibility of generating
the UUID to the clients. For a system like this, I doubt that the max value
of 64-bit integers would be reached, but the maintainability cost isn't much
higher than using integers. If anything, it at least prevents the user from
using the ID in the wrong place (i.e. `DELETE /person/1` instead of
`DELETE /city/1`) as no entity shares the same ID.
### json-patch
I used [json-patch](https://github.com/java-json-tools/json-patch) to confirm
the status of documents. Instead of sending the whole representation, only
the operation (`op`), the path (`path`) to apply it to and the new value
(`value`) have to be supplied.
## Potential improvements
A lot more tests. Integration tests, fuzz tests and benchmarks are those that come
to mind.
I would also spend a lot more time understanding cyclic dependencies when (de)serializing
JSON. For now there's a manual workaround in `SigningRequestDocumentServiceImpl.java`.