diff options
Diffstat (limited to 'src/api')
| -rw-r--r-- | src/api/login.rs | 3 | ||||
| -rw-r--r-- | src/api/store.rs | 32 | ||||
| -rw-r--r-- | src/api/users.rs | 3 |
3 files changed, 31 insertions, 7 deletions
diff --git a/src/api/login.rs b/src/api/login.rs index 023408e..b84a412 100644 --- a/src/api/login.rs +++ b/src/api/login.rs @@ -14,6 +14,7 @@ //! Every request may bring a token instead of a password: `Authorization: Bearer ct1…` //! (`bearer`). +use crate::document::signatures::Sign; use std::sync::Arc; use axum::{ @@ -261,7 +262,7 @@ pub(crate) async fn revoke_tokens(state: &AppState, name: &str, by: &str) -> Res // Issued in this very millisecond: revoked too. let after = state.clock.now_millis().as_u64() + 1; state - .mutate_doc_for(Some(by.to_owned()), move |doc| { + .mutate_doc_for(Some(by.to_owned()), Sign::Protocol, move |doc| { if !registry::exists(&*doc) { return Err(ApiError( StatusCode::CONFLICT, diff --git a/src/api/store.rs b/src/api/store.rs index 48fc2c6..7307d92 100644 --- a/src/api/store.rs +++ b/src/api/store.rs @@ -1,5 +1,6 @@ //! /store and /stream handlers. +use crate::document::signatures::Sign; use std::io::Error as IoError; use axum::{ @@ -90,12 +91,18 @@ pub(crate) struct PostQuery { /// With `cast`, how timestamps are read from and written as strings (`rfc3339` by /// default; `typed::TimestampFormat`). format: Option<String>, + /// Whether the change is signed whatever its path (`document::signatures`). + #[serde(default)] + signed: bool, } #[derive(Debug, Deserialize)] pub(crate) struct DeleteQuery { #[serde(default)] prune: bool, + /// Whether the change is signed whatever its path (`document::signatures`). + #[serde(default)] + signed: bool, } /// `GET /store`: the whole store (`docs/openapi.yaml`). @@ -349,6 +356,9 @@ pub(crate) struct PutQuery { /// default); if not, one that would is `409` (`store::Writing::retype`). #[serde(default = "yes")] retype: bool, + /// Whether the change is signed whatever its path (`document::signatures`). + #[serde(default)] + signed: bool, } fn yes() -> bool { @@ -377,6 +387,10 @@ pub(crate) async fn put_store_entry( } let path = parse_write_path(&state, &user, &access, &key, "PUT")?; + let sign = Sign::Write { + path: path.clone(), + asked: query.signed, + }; if let Some(redirect) = to_positive(&state, &path, false, None, raw_query.as_deref()).await? { return Ok(redirect); } @@ -387,7 +401,7 @@ pub(crate) async fn put_store_entry( // A value that can't be shown as asked is refused, and the write with it. let writer = user.0.clone(); let ((retyped, read), heads) = state - .mutate_doc_for(Some(user.0.clone()), move |doc| { + .mutate_doc_for(Some(user.0.clone()), sign.clone(), move |doc| { let before = Before::of(&*doc, &writer); let retyped = store::write_val_path(doc, &path, &body.value, writing) .map_err(|e| store_status(e, "Failed to write store value"))?; @@ -706,6 +720,10 @@ pub(crate) async fn post_store_entry( return Err(StatusCode::SERVICE_UNAVAILABLE.into()); } let path = parse_write_path(&state, &user, &access, &key, "POST")?; + let sign = Sign::Write { + path: path.clone(), + asked: query.signed, + }; if query.increment.is_some() && query.cast.is_some() { return Err(ApiError( StatusCode::BAD_REQUEST, @@ -723,7 +741,7 @@ pub(crate) async fn post_store_entry( if let Some(by) = query.increment { let writer = user.0.clone(); let (value, heads) = state - .mutate_doc_for(Some(user.0.clone()), move |doc| { + .mutate_doc_for(Some(user.0.clone()), sign.clone(), move |doc| { let before = Before::of(&*doc, &writer); let value = store::increment_path(doc, &path, by) .map_err(|e| store_status(e, "Failed to increment a counter"))?; @@ -759,7 +777,7 @@ pub(crate) async fn post_store_entry( // A value that can't be shown as asked is refused, and the cast with it. let writer = user.0.clone(); let ((retyped, read), heads) = state - .mutate_doc_for(Some(user.0.clone()), move |doc| { + .mutate_doc_for(Some(user.0.clone()), sign.clone(), move |doc| { let before = Before::of(&*doc, &writer); let retyped = store::cast_path(doc, &path, to, timestamps) .map_err(|e| store_status(e, "Failed to cast a store value"))?; @@ -775,7 +793,7 @@ pub(crate) async fn post_store_entry( let value = body_value(&headers, &body)?; let writer = user.0.clone(); let ((), heads) = state - .mutate_doc_for(Some(user.0.clone()), move |doc| { + .mutate_doc_for(Some(user.0.clone()), sign.clone(), move |doc| { let before = Before::of(&*doc, &writer); store::insert_val_path(doc, &path, &value.value) .map_err(|e| store_status(e, "Failed to insert into a list"))?; @@ -803,6 +821,10 @@ pub(crate) async fn delete_store_entry( RawQuery(raw_query): RawQuery, ) -> Result<Response, ApiError> { let path = parse_write_path(&state, &user, &access, &key, "DELETE")?; + let sign = Sign::Write { + path: path.clone(), + asked: query.signed, + }; tracing::Span::current().record("path", path.join("/").as_str()); @@ -826,7 +848,7 @@ pub(crate) async fn delete_store_entry( }); let writer = user.0.clone(); let ((), heads) = state - .mutate_doc_for(Some(user.0.clone()), move |doc| { + .mutate_doc_for(Some(user.0.clone()), sign.clone(), move |doc| { let before = Before::of(&*doc, &writer); store::delete_path_pruning(doc, &path, prune) .map_err(|e| store_status(e, "Failed to delete store value"))?; diff --git a/src/api/users.rs b/src/api/users.rs index 1d01af7..3b8174d 100644 --- a/src/api/users.rs +++ b/src/api/users.rs @@ -23,6 +23,7 @@ //! the document, logged, named by who made it, and refused (`409`) where it would lock //! its maker out (`access::registry_kept`). +use crate::document::signatures::Sign; use axum::{ Extension, Json, extract::{Path, State}, @@ -166,7 +167,7 @@ async fn change( let writer = user.to_owned(); let since = state.clock.now_millis().as_u64(); state - .mutate_doc_for(Some(user.to_owned()), move |doc| { + .mutate_doc_for(Some(user.to_owned()), Sign::Protocol, move |doc| { let before = Before::of(&*doc, &writer); f(doc, &by, since)?; registry_kept(&*doc, ®istry::users_dir(), before, &writer) |
