f4032e9e23
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
51 lines
2.7 KiB
Rust
51 lines
2.7 KiB
Rust
//! 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) {}
|
|
}
|