aboutsummaryrefslogtreecommitdiffstats
path: root/src/remake
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-07 22:35:21 +0100
committertv <tv@krebsco.de>2026-11-07 22:35:21 +0100
commit046b738c74f62469f7a080415690e2dacd85e1e6 (patch)
treed38a6903535d5fcc4f88e697cada351a25a3cf72 /src/remake
parentd7a6bc3ed201ff2ca953f74f62154e5e17728f22 (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/remake')
-rw-r--r--src/remake/mod.rs13
-rw-r--r--src/remake/quarantine.rs11
2 files changed, 22 insertions, 2 deletions
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,