Files: let a site owner choose and test storage (Postgres or S3) through the API, without a restart
- Dominant language
- C#
- Stars
- 6
- Forks
- 7
- Avg merge
- 4h 42m
- Merged PRs (30d)
- 307
Description
Where uploaded files are stored can only be set by an operator: environment variables or appsettings, read once at startup. A site owner cannot connect a bucket, check that it works, or switch back to the database without someone editing the server and restarting the API.
## Today
- `BarakoCMS.Files` stores bytes in Postgres (`StoredFileBlob`) unless `BarakoCMS.Files.S3` finds a bucket in `Files:S3` / `FILES__S3__*`, then every new upload goes to S3.
- Each `StoredFile` already records its `Provider` (`postgres` or `s3`) and `StorageKey`, so files written under one provider are identifiable after a switch.
- There is no way to test credentials. A wrong key or bucket appears as the first failed upload.
- Connectors (#326) already stores third-party credentials encrypted and write-only, but it models HTTP services, not object storage.
## Proposal
1. **Storage settings, per tenant, stored in the database.** Provider (`postgres` or `s3`) and, for S3, bucket, region, service URL, public base URL, `UsePublicReadAcl`, access key and secret. The secret is encrypted at rest with the existing protector, write-only, reported as `secretSet: true`.
2. **Endpoints**, gated by a new `manage_storage` capability (SuperAdmin and Admin by default):
- `GET /api/settings/storage`, which never returns the secret
- `PUT /api/settings/storage`
- `POST /api/settings/storage/test`, which puts, reads and deletes a small object with the submitted settings before they are saved, and returns which step failed and the provider's error code
3. **Switch without a restart.** Resolve storage per request from the settings, cached and invalidated on save. Reads route by each file's own `Provider`, so files already in Postgres keep working after switching to S3 and the other way round. Moving existing files is a separate, explicit action, not a side effect of saving.
4. **Environment wins.** If `FILES__S3__*` or `Files:S3` is set, the settings are read-only in the API and the response says which keys come from the environment. A deployment configured today behaves exactly as it does now (CLAUDE.md section 3).
5. **No defaults change.** A new install still stores files in Postgres.
## Out of scope here
- Moving existing files between providers (its own issue if wanted).
- An Azure Blob provider (#728) plugs into the same settings when it exists.
- Serving public files from a CDN needs #779 first.
## Done when
- Tests: a saved S3 setting routes new uploads to S3 without a restart; existing Postgres files still download; the test endpoint reports a bad secret as a failed `put` without saving anything; the secret never appears in any response; environment-set values make `PUT` refuse with a message naming them; a caller without `manage_storage` gets 403.
- The console issue in barakoBrew can be built against these endpoints alone.
Contributor guide
Research direction
Read CLAUDE.md section 3 and trace the BarakoCMS.Files storage path around StoredFileBlob and StoredFile, then identify the existing settings and authorization entry points. Use the proposed storage endpoints and the barakoBrew console requirement as the integration boundary. Done means the listed routing, testing, secret-handling, environment precedence, and 403 tests pass without requiring a restart.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- aws, csharp, postgresql
- Domain
- api, authorization, backend, databases
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100