feat(recent): update recent list server side
initially the recent was done client side
recent files are now directly updated on serverside when accessing a file
note: nextcloud and webdav voluntary not included
This commit is contained in:
@@ -20,6 +20,7 @@ pub mod music_ports;
|
||||
pub mod outbound;
|
||||
pub mod plugin_ports;
|
||||
pub mod recent_ports;
|
||||
pub mod resource_access_hook;
|
||||
pub mod share_ports;
|
||||
pub mod storage_ports;
|
||||
pub mod thumbnail_ports;
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
//! Observer notified when a caller successfully reads or mutates a file.
|
||||
//!
|
||||
//! Read-event sibling of [`crate::application::ports::file_lifecycle`]. The
|
||||
//! lifecycle hook fires on content changes (created/copied/updated/deleted);
|
||||
//! this one fires on access — every authorised file read, every successful
|
||||
//! upload, every PUT/COPY — and lets cross-cutting observers (Recent list,
|
||||
//! audit trail, future "last seen by" UX) react without each
|
||||
//! protocol-surface handler having to remember to call them.
|
||||
//!
|
||||
//! Folders are deliberately out of scope: a listing fires on every UI
|
||||
//! navigation, every PROPFIND, every NC sync poll, and would dominate
|
||||
//! `auth.user_recent_files` with noise that no user actually opened.
|
||||
//! Only file-level interactions count.
|
||||
//!
|
||||
//! Implementors run **after** the service layer's authZ check has passed and
|
||||
//! the read/write has succeeded; a denied or 404'd request never fires the
|
||||
//! hook. The method is synchronous — implementors that need to do real work
|
||||
//! spawn it themselves so the user-facing request is never blocked on the
|
||||
//! side-effect. The recording impl lives in
|
||||
//! `infrastructure/services/recent_recording_hook.rs`.
|
||||
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Fired by the application services on a successful, authorised access to a
|
||||
/// file owned (or shared with) the caller.
|
||||
///
|
||||
/// `caller_id` is mandatory because the recording side needs to know **who**
|
||||
/// touched the file — the same file accessed by two different users records
|
||||
/// two separate Recent rows. Anonymous surfaces (public share downloads via
|
||||
/// `/api/s/{token}`) deliberately do not call this hook: a "viewer" without
|
||||
/// an authenticated identity has no Recent list to land in.
|
||||
pub trait ResourceAccessHook: Send + Sync {
|
||||
/// Called after a file read or successful write touched `file_id` on
|
||||
/// behalf of `caller_id`. The caller has already been authorised — the
|
||||
/// hook is fire-and-forget; failures are the implementor's problem and
|
||||
/// must never propagate.
|
||||
fn on_file_accessed(&self, caller_id: Uuid, file_id: &str);
|
||||
|
||||
/// Called after `caller_id` has emptied their Recent list (either by
|
||||
/// clearing the whole table or removing a single row). Implementors
|
||||
/// hold in-memory throttle / dedup state keyed by `(caller, item)`;
|
||||
/// without this signal a freshly-cleared list would refuse to record
|
||||
/// the next access until the throttle TTL expires, leaving the user
|
||||
/// staring at an empty Recent and wondering why their open-then-close
|
||||
/// did nothing.
|
||||
///
|
||||
/// Default no-op: implementations without any in-memory state — most
|
||||
/// audit-trail-style observers — needn't react.
|
||||
fn on_recents_cleared(&self, _caller_id: Uuid) {}
|
||||
}
|
||||
Reference in New Issue
Block a user