feat(file-storage): setup s3 storage - #481
Open
BanelhaqB wants to merge 6 commits into
Open
Conversation
The port used to speak filesystem: get(path), deleteByPath(path) and an upload returning an absolute path. Plugging S3 under that vocabulary would have made the abstraction lie about what it does. Upload now returns a locator that is opaque to the domain: it is persisted as File.uri and handed back to the very same adapter to read or delete the content. Each adapter picks its own format, so the local adapter keeps writing and reading the exact same absolute paths as before and no stored row becomes invalid. Also drops delete(UUID), which no production code ever called. refs: #2321
FileDtoMapper exposed File.uri straight as the DTO url, and the shared
FileDTOMapper concatenated the request origin with it. Both leaked a
storage locator to clients: in production the second one produced URLs
like https://host/workspace/app/target/storage/<uuid>.png, which no route
serves — the Apache overlay has no alias for that path.
Both now point at the /storage/{fileId} endpoint, the way FileDataMapper
already did. The construction is centralised in FileStorageConstants so
the three call sites cannot drift apart again.
This changes the url field returned by the trace, feedback, user photo and
activity file endpoints.
refs: #2321
S3FileStorageService stores objects under the {uuid}.{extension} key and
hands that key back as the locator. The content type is set on the object
so a client reading it back is told what it is rather than getting
application/octet-stream.
The two real adapters are mutually exclusive on file.storage.type and both
keep @primary, which the seeder mock relies on to stay resolvable through
its own qualifier. Local storage remains the default, so nothing changes
until the property is set to s3.
Behaviour difference worth knowing: S3 answers successfully when deleting a
key that does not exist, so the adapter cannot report a missing file the way
the local one does.
Default profile and cover pictures are now read as Spring resource
locations instead of going through the storage backend. They ship with the
deployment and belong to no user, so routing a static asset through the
bucket would have tied it to the backend availability.
Keys are flat for now. Prefixing them per domain needs the upload signatures
to carry the calling context, which is the streaming refactor's job.
refs: #2321
S3FileStorageServiceTest pins the contract against a mocked client: key format, content type, and the translation of a missing key into FileNotFoundException. S3FileStorageServiceIT runs the same operations against a MinIO container, including the delete-then-read round trip and the fact that deleting an unknown key succeeds. It instantiates the adapter directly rather than extending ContainerConfigurationTest, since booting the application context would cover nothing more here. FileStorageBackendSelectionTest guards the file.storage.type switch: both adapters are marked primary, so a regression registering the two at once would break every injection point. The testcontainers MinIO module is not published for the 2.x line Spring Boot 4 manages, so the container is a plain GenericContainer instead. refs: #2321
The hosted bucket lives in Paris, so us-east-1 was a misleading default for the online backend. Local MinIO keeps us-east-1, which is its conventional value and which it ignores anyway. refs: #2321
Nathan-Pignon
approved these changes
Sep 3, 2026
Nathan-Pignon
left a comment
Collaborator
There was a problem hiding this comment.
Quelques suggestions mais sinon c'est good pour moi, merci Bilel !
Comment on lines
+86
to
+88
| file.storage.s3.bucket=b4d61f49-e303-4f97-8736-924372b513ff | ||
| file.storage.s3.access-key=ENC(CNyV3T3tgXUc7DBXo5thx3L9uMEipDFzF+7i1c8pOj0=) | ||
| file.storage.s3.secret-key=ENC(NVre2sSEsYv2cvLlz5v5MKcQewIZg/6WEpALQ+smK4WoohZ6j1Hj26+ClqzROF9s9yVWtswwAG0=) |
Collaborator
There was a problem hiding this comment.
Je sais pas ce que tu en penses mais j'aurais peut-être mis ces trois props dans le env.properties ? Puis mettre à jour le script qui génère le env.properties ducoup
Enable the S3 properties with the encrypted dev credentials. The backend stays inactive until file.storage.type is switched to s3. refs: #2321
BanelhaqB
force-pushed
the
feat/2321-migration-systeme-stockage-s3
branch
from
September 3, 2026 16:51
5c4f610 to
1e07272
Compare
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
📝 Pull Request Description
Brief description of changes applied
Reference to an Issue, Feature, Task, User Story or another PR
Documentation
Target Branch
Additional Notes
Known Limitations or Side Effects
✅ Checklist
Please make sure you have addressed the following before submitting:
S3FileStorageServiceTest,S3FileStorageServiceIT,FileStorageBackendSelectionTest,StorageControllerITCHANGELOG.mdfile all properties and database change and details for the update process