Edouard Vanbelle
dfb21b746d
feat(openapi): show explicitly path requiring bearerAuth
2026-05-28 00:48:20 +02:00
Edouard Vanbelle
de1645b6c3
feat(openapi): add /api/auth to openapi declaration
2026-05-28 00:20:21 +02:00
Edouard Vanbelle
5afb30ebfd
feat(swimlane): add swimlane engine with first version on SharedWithMe section
...
added group by:
- None (= ordered by folders/file name)
- Type (Folder first, then Image, Vidao, Audio, Document, etc...)
- Owner
- Size (With logarithmic groups))
- Shared date (with groups: today, last 7 days, last 30 days, then year)
2026-05-28 00:15:05 +02:00
Edouard Vanbelle
c65f2b5385
feat(api): cursor listing contract — PageCursor trait + resource field
...
- Add src/application/dtos/cursor.rs with three shared types:
· PageCursor trait — default base64url+JSON encode/decode; one bare
impl line per cursor struct
· CursorQuery struct — standard limit/cursor/sort_by query params with
limit_clamped() and decode_cursor<C>() helpers; compose via flatten
· CursorListResponse<T> — standard {items, next_cursor?} envelope with
from_oversized() and with_cursor() builders
- Migrate GrantCursor to impl PageCursor (remove duplicate encode/decode)
- Update GET /api/grants/incoming/resources:
· SharedWithMeQuery now embeds CursorQuery via #[serde(flatten)]
· Replace file/folder nullable pair with ResourceContentDto (untagged
enum) under a single always-present 'resource' field
· SharedWithMeDto is now a type alias for CursorListResponse<SharedWithMeItemDto>
· Handler uses q.paging.limit_clamped() and decode_cursor<GrantCursor>()
- Add docs/architecture/resource-listing.md — authoritative contract for
all listing endpoints (cursor design, SQL keyset WHERE, sort_by naming,
Rust + JS skeletons, compliance table, migration guide)
- Register doc in VitePress sidebar and architecture index
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com >
2026-05-28 00:15:04 +02:00
Edouard Vanbelle
4a5e9a67ca
permits img-src from external website, other solution is to store base64 image of user in DB
...
note: if we need to keep this security, we need to store all user's images (blob_storage can be a good candidate)
2026-05-27 11:29:33 +02:00
Edouard Vanbelle
b0c5e7827e
feat(user-avatar): users can now edit there image (image is taken from OIDC picture)
2026-05-27 11:29:33 +02:00
Edouard Vanbelle
8365608bd5
feat(list view): show the owner of the File or Folder in list view
2026-05-25 22:48:59 +02:00
Edouard Vanbelle
79c1a37931
feat(ui): 1 modal to manage shares (users & public share)
...
fix(share): ensure Authz parent is created/updated on publicShare create/update
fix(ShareModal): do not show Token (public) grants in People section
2026-05-25 22:47:36 +02:00
Edouard Vanbelle
12466d4b83
feat(roles): simplify roles to only Viewer, Editor, Admin
...
┌────────┬──────┬─────────┬────────┬────────┬───────┬────────┐
│ Role │ read │ comment │ create │ update │ share │ delete │
├────────┼──────┼─────────┼────────┼────────┼───────┼────────┤
│ viewer │ ✓ │ │ │ │ │ │
├────────┼──────┼─────────┼────────┼────────┼───────┼────────┤
│ editor │ ✓ │ ✓ │ ✓ │ ✓ │ │ │
├────────┼──────┼─────────┼────────┼────────┼───────┼────────┤
│ admin │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │ ✓ │
└────────┴──────┴─────────┴────────┴────────┴───────┴────────┘
2026-05-25 22:47:36 +02:00
Edouard Vanbelle
143b13d7bc
security(authz): a shared item must not return it's full path
2026-05-25 22:47:01 +02:00
Edouard Vanbelle
093c1ad3a5
feat(grants): add /api/grants/incoming/resources with a cursor for pagination
2026-05-25 22:47:01 +02:00
Edouard Vanbelle
50d13943fc
fix(grants): show /grants on openapi
2026-05-25 22:47:01 +02:00
Edouard Vanbelle
73f0b0fa47
refactor(lifecycle hooks): simplify integration of new services
...
* make more coherent lifecycles
* remove specific implementation on different handlers (they do not need to know existence of ThumbnailSerice nor AudioMetadataService)
* reduce risk of orphean objects
* ensure additional services are correctly wired (ex: Thumbnail generation was not covering all upload cases)
* more details on docs/architecture/file-and-blob-lifecycle.md :
```rust
// application/ports/file_lifecycle.rs
pub trait FileLifecycleHook {
fn on_file_created(file_id, blob_hash, content_type, is_new_blob);
fn on_file_updated(file_id, blob_hash, content_type);
fn on_file_copied(file_id, blob_hash, content_type, source_id)
fn on_file_deleted(file_id);
}
// application/ports/blob_lifecycle.rs
pub trait BlobLifecycleHook {
fn on_blob_created(blob_hash, content_type);
fn on_blob_deleted(blob_hash);
}
```
2026-05-22 13:40:58 +02:00
Edouard Vanbelle
191f725199
feat(ui/trash): show original file path in tooltip on mouse over + display thumbnails
...
* fix: permission also check elements trashed elements
* tested manually
* all automated tests ok
2026-05-22 02:26:11 +02:00
Edouard Vanbelle
76a85949e7
fix(trash)+refactor(file life cycle)
...
* fix issue with the empty trash (wasn't calling thumbnail clean up)
* refactor file service life cycle (TrashService don't call directly ThumbnailService, but call the on_file_deleted() hook
* remove unused mehod: _validate_user_ownership()
2026-05-22 00:28:39 +02:00
Edouard Vanbelle
dd68d783e0
fix(authz): permit policiy: a user with Delete permission can delete a file/folder. Only the owner can permanently delete or restore a trashed item
2026-05-21 22:45:49 +02:00
Edouard Vanbelle
a1c21ce446
refactor(authz): permet require_permission() as has_permission(), more explicit
2026-05-21 21:50:42 +02:00
Edouard Vanbelle
cb35775f77
fix(dedub): correct ref count on hashes, many thanks to you api tests...
2026-05-21 21:12:38 +02:00
Edouard Vanbelle
eb95567a7d
feat(authz): test & cover batch cases
...
┌────────────────────────────────┬─────────────────────────────────┬───────────────────────┬─────────────────┬──────────────────────────────┐
│ Endpoint │ Phase 3A no-grant │ Phase 3B Viewer │ Phase 3C Editor │ Phase 3D Admin │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/files/get │ 400 (all failed) │ 200 (2 successful) │ — │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/files/move │ 400 │ 400 (no Update) │ 200 │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/files/copy │ 400 │ — │ 200 │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/files/delete │ 400 │ 400 │ 400 (no Delete) │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/folders/get │ 400 │ 200 │ — │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/folders/create │ 400 │ — │ 201 │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/folders/move │ 400 │ — │ 200 │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/folders/copy │ 400 │ — │ 200 │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/folders/delete │ 400 │ — │ 400 (no Delete) │ 200 │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/trash │ 400 │ — │ — │ 400 (owner-only, documented) │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ POST /api/batch/download │ 404 (NotFound) │ 200 + application/zip │ — │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ GET /api/batch/download?... │ 404 │ 200 + zip │ — │ — │
├────────────────────────────────┼─────────────────────────────────┼───────────────────────┼─────────────────┼──────────────────────────────┤
│ Phase 3E lifecycle cleanup │ grants table empty after delete │ │ │ │
└────────────────────────────────┴─────────────────────────────────┴───────────────────────┴─────────────────┴──────────────────────────────┘
2026-05-21 20:30:58 +02:00
Edouard Vanbelle
a53c09f361
feat(authz): covert and test chunked upload with permissions
2026-05-21 20:30:58 +02:00
Edouard Vanbelle
3362e277ab
feat(authz): check permission on read handlers + check create permission on folder
2026-05-21 20:30:53 +02:00
Edouard Vanbelle
cba9be8c21
feat(rebac): first pass
2026-05-20 22:56:00 +02:00
Edouard Vanbelle
dfb082fdf4
refactor(server): file_management_service: move all method without owner check into private, add folder_ports
2026-05-20 15:39:53 +02:00
Edouard Vanbelle
f8b30e78a6
refactor(create_folder): add an ownership check while creating a folder + refactor code
2026-05-20 12:59:04 +02:00
Edouard Vanbelle
79a12018b1
fix(folder_service): propagate 409 error if folder aleady exists
2026-05-19 10:18:40 +02:00
Edouard Vanbelle
a38475bd2c
style(server): align text
2026-05-19 09:42:44 +02:00
Edouard Vanbelle
edbfe2848c
fix(front): fix issue with already declared constants on release mode
...
- ensure not loading twice the same variables, namespace to ensure it in the future
- end to end tests where successfull, need to check it is not reusing a previous release (in cache from build CI)
- fix : #377 #378
2026-05-19 09:36:24 +02:00
Edouard Vanbelle
815c9df613
feat(server): add support of IPv6 (no dual stack)
2026-05-14 20:11:12 +02:00
Edouard Vanbelle
059469c0cc
feat(openapi): complete openapi with new shares routes
...
- GET /api/s/{token}/contents — list root folder of a shared folder
- GET /api/s/{token}/contents/{folder_id} — list subfolder
- GET /api/s/{token}/file/{file_id} — download a file within a shared folder
- GET /api/s/{token}/zip — download root as ZIP
- GET /api/s/{token}/zip/{folder_id} — download subfolder as ZIP
(added from @abnvle)
2026-05-14 00:50:15 +02:00
Dionisio Pozo
1e34c5f3f8
Merge pull request #330 from EdouardVanbelle/fix/thumbnail-on-update
...
bugfix/thumbnails on update
2026-05-14 00:38:03 +02:00
Edouard Vanbelle
d85b8055b8
refactor(services): add file_lifecycle and blob_lifecycle
...
- complete src/application/ports/blob_lifecycle.rs with traits:
* BlobCreationHook
* BlobDeletionHook
- add src/application/ports/file_lifecycle.rs with traits:
* FileCreatedHook
* FileDeletedHook
* FileUpdatedHook
2026-05-14 00:18:12 +02:00
Dionisio Pozo
412e31388d
Merge pull request #347 from abnvle/feat/share-folder-browsing
2026-05-14 00:07:45 +02:00
Edouard Vanbelle
28e25f9d16
fix+test: check hash ref count on copy-on-write (a duplicated beeing updated)
2026-05-13 15:55:41 +02:00
Edouard Vanbelle
78cb37b311
feat: check thumbnail cleanup on files deletion + correct ref counter
2026-05-13 15:55:38 +02:00
Edouard Vanbelle
9dd5877bb2
chore: update comments to reflect hash alg used (SHA-256 -> Blake3)
2026-05-13 15:55:37 +02:00
Edouard Vanbelle
9f57776ec9
bugfix/thumbnails on update
...
Bug 1 & 2 (webdav_handler.rs handle_put() update branch):
- After a successful file update via WebDAV PUT, if the content type is a supported image:
a. delete_thumbnails(file_id) — evicts the stale moka cache entry
b. Spawns a background task to read the new blob bytes and call generate_all_sizes_background_from_bytes
Bug 3 & 4 (dedup_service.rs):
- Added thumbnail_service: Option<Arc<ThumbnailService>> field with a with_thumbnail_service() builder
- In remove_legacy_reference(): calls delete_blob_thumbnails(hash) when ref_count hits 0
- In remove_manifest_reference(): calls delete_blob_thumbnails(file_hash) when manifest's last ref is dropped
- Wired in di.rs — the thumbnail service is created before dedup service so the ordering works cleanly
2026-05-12 09:00:26 +02:00
Edouard Vanbelle
1afacb65cd
style(srv): correct clippy recos
2026-05-12 00:34:11 +02:00
Edouard Vanbelle
b4d4056a15
fix/security: move_folder(): check that target belongs to caller
2026-05-12 00:29:04 +02:00
Edouard Vanbelle
3a18507158
fix/security: copy_file_owned(): ensure that target is also owned by the user
2026-05-12 00:28:42 +02:00
Edouard Vanbelle
2f49daa4ee
feat(folders): implement copy_folders taking care of ownership
2026-05-12 00:22:51 +02:00
Edouard Vanbelle
03aac93db3
chore: add /status /ready best practices for Docker & K8S
2026-05-11 00:53:25 +02:00
Edouard Vanbelle
ad711e18ea
feat(contacts): add feature flag to enable/disable exposition of users in address-book
2026-05-10 22:12:11 +02:00
abnvle
e8399443e9
Merge remote-tracking branch 'origin/main' into feat/share-folder-browsing
...
# Conflicts:
# static/js/views/public/publicShare.js
2026-05-10 20:46:29 +02:00
abnvle
ec55e7ec55
fix(share): tighten public browsing (UUID guard, cache headers, abort race)
2026-05-10 20:43:59 +02:00
Edouard Vanbelle
89ec0d2c24
feat(contacts): add API to address-books, contacts, groups
...
* full gateway to /carddav
* add system readonly address-book issued from OxiCloud users
2026-05-10 00:39:25 +02:00
Dionisio Pozo
a6eb81a13a
Merge pull request #354 from EdouardVanbelle/feat/ui-error-handling
2026-05-09 00:27:48 +02:00
Edouard Vanbelle
7697f3d35b
feat(ui): handle errors on folder creation or folder/file renaming
...
- protect file_management_service::rename_file with validate_storage_name
- remove specific rename modal and use the generic modal class (less duplicate)
- handle errors on modal action: do not close the modal on error and display this error
- hide "Go to parent folder" contextMenu if section is files and folder is the same as current one
2026-05-09 00:06:36 +02:00
Dionisio Pozo
cbddbdc3d5
Merge pull request #320 from EdouardVanbelle/feat/client_ip
2026-05-08 23:55:41 +02:00
Dionisio Pozo
52f4a865a9
Merge pull request #349 from EdouardVanbelle/feat/item-path-tool-tip+go-to-parent
...
show item path on Recent + Favorite, add go to parent folder, fix Folder browsing in Favorites
2026-05-08 01:22:08 +02:00
Dionisio Pozo
fec9bb1f96
Merge pull request #351 from EdouardVanbelle/security/refresh-token-rotation
...
security: prevent re-use of refresh token (reduce surface for any stolen token)
2026-05-08 01:21:27 +02:00