diff options
| author | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
|---|---|---|
| committer | tv <tv@krebsco.de> | 2026-11-07 22:35:21 +0100 |
| commit | 046b738c74f62469f7a080415690e2dacd85e1e6 (patch) | |
| tree | d38a6903535d5fcc4f88e697cada351a25a3cf72 /src | |
| parent | d7a6bc3ed201ff2ca953f74f62154e5e17728f22 (diff) | |
remake: forgetting and releasing name their user
Forget records and released quarantines name the user who made them,
so they are judged by its capabilities.
Auth plan M6.
Diffstat (limited to 'src')
| -rw-r--r-- | src/api/peers.rs | 15 | ||||
| -rw-r--r-- | src/remake/mod.rs | 13 | ||||
| -rw-r--r-- | src/remake/quarantine.rs | 11 | ||||
| -rw-r--r-- | src/state/host.rs | 19 |
4 files changed, 52 insertions, 6 deletions
diff --git a/src/api/peers.rs b/src/api/peers.rs index b00593f..cd9381f 100644 --- a/src/api/peers.rs +++ b/src/api/peers.rs @@ -252,6 +252,7 @@ pub(crate) async fn peer_list(state: &AppState) -> PeerListResponse { /// `DELETE /peers/{pk}`: forgets a peer swarm-wide. pub(crate) async fn delete_peer( State(state): State<AppState>, + user: Option<axum::Extension<crate::api::auth::AuthenticatedUser>>, Path(peer): Path<String>, Query(query): Query<DeletePeerQuery>, ) -> Result<StatusCode, StatusCode> { @@ -279,11 +280,17 @@ pub(crate) async fn delete_peer( serde_json::json!({ "at": state.clock.now_millis().as_u64(), "by": state.local_id() }); let peer_clone = peer.clone(); + // Named as who asked: rules by path judge the change by them (`access::rules`). + let user = user.map(|axum::Extension(user)| user.0); state - .mutate_doc(move |doc| { - store::write_path(doc, &forgotten_path(&peer_clone), &record)?; - crate::swarm::members::unregister(doc, &peer_clone) - }) + .mutate_doc_for( + user, + crate::document::signatures::Sign::Protocol, + move |doc| { + store::write_path(doc, &forgotten_path(&peer_clone), &record)?; + crate::swarm::members::unregister(doc, &peer_clone) + }, + ) .await .map_err(|e| store_status(e, "Failed to write forget record").status())?; diff --git a/src/remake/mod.rs b/src/remake/mod.rs index 67fa77b..342eab3 100644 --- a/src/remake/mod.rs +++ b/src/remake/mod.rs @@ -297,6 +297,19 @@ pub(crate) trait Host: Clone + Send + Sync + 'static { T: Send + 'static, E: From<StoreError> + Send + 'static; + /// [`commit_doc`](Self::commit_doc) for `user`, who asked through the API: the + /// change names them (`replica::Writer`), as rules by path judge it + /// (`access::rules`). + fn commit_doc_for<T, E, F>( + &self, + user: Option<String>, + f: F, + ) -> impl Future<Output = Result<T, E>> + Send + where + F: FnOnce(&mut Transaction<'_>) -> Result<T, E> + Send + 'static, + T: Send + 'static, + E: From<StoreError> + Send + 'static; + /// What a replay does with writes a newer one superseded (`--superseded-writes`). fn superseded(&self) -> Superseded; diff --git a/src/remake/quarantine.rs b/src/remake/quarantine.rs index bb34d73..e7214d6 100644 --- a/src/remake/quarantine.rs +++ b/src/remake/quarantine.rs @@ -159,7 +159,13 @@ pub(crate) async fn document<H: Host>(State(host): State<H>, Path(id): Path<Stri } } -pub(crate) async fn replay<H: Host>(State(host): State<H>, Path(id): Path<String>) -> Response { +/// `POST /admin/quarantine/{id}/replay`: the entry's paths written as they were, +/// by the user who asked (`access::rules` judges the change by them). +pub(crate) async fn replay<H: Host>( + State(host): State<H>, + user: Option<axum::Extension<crate::api::auth::AuthenticatedUser>>, + Path(id): Path<String>, +) -> Response { if !host.is_node_ready().await { return error_response(StatusCode::SERVICE_UNAVAILABLE, "node is not ready", None); } @@ -170,7 +176,8 @@ pub(crate) async fn replay<H: Host>(State(host): State<H>, Path(id): Path<String let entry = Arc::new(entry); let replayed = { let entry = Arc::clone(&entry); - host.commit_doc(move |doc| { + let user = user.map(|axum::Extension(user)| user.0); + host.commit_doc_for(user, move |doc| { // As they are: the operator decided they belong at their old paths. Ok::<_, StoreError>(delta::replay_paths( &entry.document, diff --git a/src/state/host.rs b/src/state/host.rs index 47fd946..a48a6fb 100644 --- a/src/state/host.rs +++ b/src/state/host.rs @@ -246,6 +246,25 @@ impl Host for AppState { async move { state.mutate_doc(f).await } } + fn commit_doc_for<T, E, F>( + &self, + user: Option<String>, + f: F, + ) -> impl Future<Output = Result<T, E>> + Send + where + F: FnOnce(&mut Transaction<'_>) -> Result<T, E> + Send + 'static, + T: Send + 'static, + E: From<StoreError> + Send + 'static, + { + let state = self.clone(); + async move { + state + .mutate_doc_for(user, crate::document::signatures::Sign::Protocol, f) + .await + .map(|(out, _)| out) + } + } + fn superseded(&self) -> crate::remake::Superseded { self.superseded_writes } |
