summaryrefslogtreecommitdiffstats
path: root/src/api/store.rs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-10-24 19:25:54 +0200
committertv <tv@krebsco.de>2026-10-24 19:25:54 +0200
commit815ec2e9a641ad5ac5c2f886291e63c89966bd6c (patch)
tree5840ab9e9adc8e5ab5259ef0da7949880cde5f53 /src/api/store.rs
parent09f2dfd083c4fcdce4c5ca7376353906eb025c42 (diff)
only protocol-writers may modify _continuum
Diffstat (limited to 'src/api/store.rs')
-rw-r--r--src/api/store.rs12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/api/store.rs b/src/api/store.rs
index d6ff306..aa9465c 100644
--- a/src/api/store.rs
+++ b/src/api/store.rs
@@ -4,6 +4,7 @@ use std::io::Error as IoError;
use automerge::ChangeHash;
use axum::{
+ Extension,
body::{Body, Bytes},
extract::{Path, Query, State},
http::{
@@ -17,7 +18,8 @@ use serde_json::Value as JsonValue;
use tokio::sync::broadcast;
use tracing::{debug, error, instrument};
-use super::{parse_key_path, response_for_value, store_status};
+use super::auth::AuthenticatedUser;
+use super::{parse_key_path, parse_write_path, response_for_value, store_status};
use crate::document::store::{self, StoreError};
use crate::state::{AppState, ReadSource};
use crate::swarm::sync::paths_related;
@@ -194,6 +196,7 @@ fn mark_source(
responses(
(status = 200, description = "Value written successfully"),
(status = 400, description = "Invalid path, malformed JSON, invalid UTF-8, or unsupported JSON value"),
+ (status = 403, description = "Protocol data (_continuum) and the user isn't a protocol writer, or epoch metadata"),
(status = 409, description = "Path conflicts with an existing non-map value"),
(status = 415, description = "Unsupported Content-Type"),
(status = 500, description = "Internal error or synchronization notification failure"),
@@ -202,6 +205,7 @@ fn mark_source(
)]
pub(crate) async fn put_store_entry(
State(state): State<AppState>,
+ Extension(user): Extension<AuthenticatedUser>,
Path(key): Path<String>,
headers: HeaderMap,
body: Bytes,
@@ -210,7 +214,7 @@ pub(crate) async fn put_store_entry(
return Err(StatusCode::SERVICE_UNAVAILABLE);
}
- let path = parse_key_path(&key)?;
+ let path = parse_write_path(&state, &user, &key, "PUT")?;
let content_type = headers
.get(CONTENT_TYPE)
@@ -251,6 +255,7 @@ pub(crate) async fn put_store_entry(
responses(
(status = 204, description = "Value deleted successfully"),
(status = 400, description = "Invalid store path"),
+ (status = 403, description = "Protocol data (_continuum) and the user isn't a protocol writer, or epoch metadata"),
(status = 404, description = "Value does not exist"),
(status = 500, description = "Deletion or synchronization notification failed"),
(status = 503, description = "Node is not ready")
@@ -259,10 +264,11 @@ pub(crate) async fn put_store_entry(
#[instrument(skip(state), fields(path, prune = query.prune))]
pub(crate) async fn delete_store_entry(
State(state): State<AppState>,
+ Extension(user): Extension<AuthenticatedUser>,
Path(key): Path<String>,
Query(query): Query<DeleteQuery>,
) -> Result<StatusCode, StatusCode> {
- let path = parse_key_path(&key)?;
+ let path = parse_write_path(&state, &user, &key, "DELETE")?;
tracing::Span::current().record("path", path.join("/").as_str());