From 6f2d556c65940a360e574d844383d1bd4626008e Mon Sep 17 00:00:00 2001 From: trisua Date: Sat, 19 Jul 2025 23:21:01 -0400 Subject: [PATCH] add: app data rename method --- Cargo.lock | 8 ++--- crates/app/Cargo.toml | 2 +- crates/app/src/main.rs | 2 +- crates/app/src/public/js/app_sdk.js | 24 ++++++++++++++ crates/app/src/routes/api/v1/app_data.rs | 41 +++++++++++++++++++++++- crates/app/src/routes/api/v1/mod.rs | 6 ++++ crates/core/Cargo.toml | 6 ++-- crates/core/src/sdk.rs | 19 +++++++++++ crates/l10n/Cargo.toml | 2 +- crates/shared/Cargo.toml | 2 +- 10 files changed, 100 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a3a09d1..b03e9ca 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3269,7 +3269,7 @@ dependencies = [ [[package]] name = "tetratto" -version = "11.0.0" +version = "12.0.0" dependencies = [ "ammonia", "async-stripe", @@ -3301,7 +3301,7 @@ dependencies = [ [[package]] name = "tetratto-core" -version = "11.0.0" +version = "12.0.0" dependencies = [ "async-recursion", "base16ct", @@ -3325,7 +3325,7 @@ dependencies = [ [[package]] name = "tetratto-l10n" -version = "11.0.0" +version = "12.0.0" dependencies = [ "pathbufd", "serde", @@ -3334,7 +3334,7 @@ dependencies = [ [[package]] name = "tetratto-shared" -version = "11.0.0" +version = "12.0.0" dependencies = [ "ammonia", "chrono", diff --git a/crates/app/Cargo.toml b/crates/app/Cargo.toml index 09efda7..e5ca15f 100644 --- a/crates/app/Cargo.toml +++ b/crates/app/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "tetratto" -version = "11.0.0" +version = "12.0.0" edition = "2024" authors.workspace = true repository.workspace = true diff --git a/crates/app/src/main.rs b/crates/app/src/main.rs index 8347c23..bfac36f 100644 --- a/crates/app/src/main.rs +++ b/crates/app/src/main.rs @@ -131,7 +131,7 @@ async fn main() { let client = Client::new(); let mut app = Router::new(); - // cretae stripe client + // create stripe client let stripe_client = if let Some(ref stripe) = config.stripe { Some(StripeClient::new(stripe.secret.clone())) } else { diff --git a/crates/app/src/public/js/app_sdk.js b/crates/app/src/public/js/app_sdk.js index 2ca1f53..cd21e6a 100644 --- a/crates/app/src/public/js/app_sdk.js +++ b/crates/app/src/public/js/app_sdk.js @@ -140,6 +140,29 @@ export default function tetratto({ ); } + async function rename(id, key) { + if (!api_key) { + throw Error("No API key provided."); + } + + return api_promise( + json_parse( + await ( + await fetch(`${host}/api/v1/app_data/${id}/key`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "Atto-Secret-Key": api_key, + }, + body: json_stringify({ + key, + }), + }) + ).text(), + ), + ); + } + async function remove(id) { if (!api_key) { throw Error("No API key provided."); @@ -265,6 +288,7 @@ export default function tetratto({ query, insert, update, + rename, remove, remove_query, // user connection diff --git a/crates/app/src/routes/api/v1/app_data.rs b/crates/app/src/routes/api/v1/app_data.rs index f9da1c8..d5e8c3f 100644 --- a/crates/app/src/routes/api/v1/app_data.rs +++ b/crates/app/src/routes/api/v1/app_data.rs @@ -1,6 +1,6 @@ use crate::{ get_app_from_key, - routes::api::v1::{InsertAppData, QueryAppData, UpdateAppDataValue}, + routes::api::v1::{InsertAppData, QueryAppData, UpdateAppDataValue, UpdateAppDataKey}, State, }; use axum::{extract::Path, http::HeaderMap, response::IntoResponse, Extension, Json}; @@ -94,6 +94,37 @@ pub async fn create_request( } } +pub async fn update_key_request( + headers: HeaderMap, + Extension(data): Extension, + Path(id): Path, + Json(req): Json, +) -> impl IntoResponse { + let data = &(data.read().await).0; + let app = match get_app_from_key!(data, headers) { + Some(x) => x, + None => return Json(Error::NotAllowed.into()), + }; + + let app_data = match data.get_app_data_by_id(id).await { + Ok(x) => x, + Err(e) => return Json(e.into()), + }; + + if app_data.app != app.id { + return Json(Error::NotAllowed.into()); + } + + match data.update_app_data_key(id, &req.key).await { + Ok(_) => Json(ApiReturn { + ok: true, + message: "Data updated".to_string(), + payload: (), + }), + Err(e) => Json(e.into()), + } +} + pub async fn update_value_request( headers: HeaderMap, Extension(data): Extension, @@ -116,6 +147,10 @@ pub async fn update_value_request( Err(e) => return Json(e.into()), }; + if app_data.app != app.id { + return Json(Error::NotAllowed.into()); + } + // check size let size_without = app.data_used - app_data.value.len(); let new_size = size_without + req.value.len(); @@ -155,6 +190,10 @@ pub async fn delete_request( Err(e) => return Json(e.into()), }; + if app_data.app != app.id { + return Json(Error::NotAllowed.into()); + } + // ... if let Err(e) = data .add_app_data_used(app.id, -(app_data.value.len() as i32)) diff --git a/crates/app/src/routes/api/v1/mod.rs b/crates/app/src/routes/api/v1/mod.rs index 60bbf20..6b56e9b 100644 --- a/crates/app/src/routes/api/v1/mod.rs +++ b/crates/app/src/routes/api/v1/mod.rs @@ -439,6 +439,7 @@ pub fn routes() -> Router { .route("/app_data", post(app_data::create_request)) .route("/app_data/app", get(app_data::get_app_request)) .route("/app_data/{id}", delete(app_data::delete_request)) + .route("/app_data/{id}/key", post(app_data::update_key_request)) .route("/app_data/{id}/value", post(app_data::update_value_request)) .route("/app_data/query", post(app_data::query_request)) .route("/app_data/query", delete(app_data::delete_query_request)) @@ -1176,6 +1177,11 @@ pub struct UpdateUploadAlt { pub alt: String, } +#[derive(Deserialize)] +pub struct UpdateAppDataKey { + pub key: String, +} + #[derive(Deserialize)] pub struct UpdateAppDataValue { pub value: String, diff --git a/crates/core/Cargo.toml b/crates/core/Cargo.toml index 2dd5dfa..98a0947 100644 --- a/crates/core/Cargo.toml +++ b/crates/core/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tetratto-core" description = "The core behind Tetratto" -version = "11.0.0" +version = "12.0.0" edition = "2024" authors.workspace = true repository.workspace = true @@ -18,8 +18,8 @@ default = ["database", "types", "sdk"] pathbufd = "0.1.4" serde = { version = "1.0.219", features = ["derive"] } toml = "0.9.2" -tetratto-shared = { version = "11.0.0", path = "../shared" } -tetratto-l10n = { version = "11.0.0", path = "../l10n" } +tetratto-shared = { version = "12.0.0", path = "../shared" } +tetratto-l10n = { version = "12.0.0", path = "../l10n" } serde_json = "1.0.141" totp-rs = { version = "5.7.0", features = ["qr", "gen_secret"], optional = true } reqwest = { version = "0.12.22", features = ["json", "multipart"], optional = true } diff --git a/crates/core/src/sdk.rs b/crates/core/src/sdk.rs index 72b82e8..71ba502 100644 --- a/crates/core/src/sdk.rs +++ b/crates/core/src/sdk.rs @@ -129,6 +129,25 @@ impl DataClient { } } + /// Update a record's key given its ID and the new key. + pub async fn rename(&self, id: usize, key: String) -> Result<()> { + match self + .http + .post(format!("{}/api/v1/app_data/{id}/key", self.host)) + .header("Atto-Secret-Key", &self.api_key) + .json(&serde_json::Value::Object({ + let mut map = serde_json::Map::new(); + map.insert("key".to_string(), serde_json::Value::String(key)); + map + })) + .send() + .await + { + Ok(x) => api_return_ok!((), x), + Err(e) => Err(Error::MiscError(e.to_string())), + } + } + /// Delete a row from the app's data by its `id`. pub async fn remove(&self, id: usize) -> Result<()> { match self diff --git a/crates/l10n/Cargo.toml b/crates/l10n/Cargo.toml index 6b8cb59..5993ffc 100644 --- a/crates/l10n/Cargo.toml +++ b/crates/l10n/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tetratto-l10n" description = "Localization for Tetratto" -version = "11.0.0" +version = "12.0.0" edition = "2024" authors.workspace = true repository.workspace = true diff --git a/crates/shared/Cargo.toml b/crates/shared/Cargo.toml index 38fd768..02b14fc 100644 --- a/crates/shared/Cargo.toml +++ b/crates/shared/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "tetratto-shared" description = "Shared stuff for Tetratto" -version = "11.0.0" +version = "12.0.0" edition = "2024" authors.workspace = true repository.workspace = true