From 7ed0af4750b1c03c6b7713646335b7b5b024507d Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Mon, 17 Oct 2022 02:00:15 +0100 Subject: [PATCH] Add support for SQL parameters in HTTP REST endpoints --- src/net/key.rs | 19 +++++++++++++++++++ src/net/mod.rs | 1 + src/net/params.rs | 24 ++++++++++++++++++++++++ src/net/sql.rs | 5 ++++- 4 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/net/params.rs diff --git a/src/net/key.rs b/src/net/key.rs index 923f1dc5..630d1abe 100644 --- a/src/net/key.rs +++ b/src/net/key.rs @@ -2,6 +2,7 @@ use crate::cli::CF; use crate::dbs::DB; use crate::err::Error; use crate::net::output; +use crate::net::params::Params; use crate::net::session; use bytes::Bytes; use serde::Deserialize; @@ -47,6 +48,7 @@ pub fn config() -> impl Filter impl Filter(http::header::ACCEPT.as_str())) .and(path!("key" / String).and(warp::path::end())) + .and(warp::query()) .and(session::build()) .and_then(delete_all); // Specify route @@ -77,6 +80,7 @@ pub fn config() -> impl Filter impl Filter impl Filter impl Filter(http::header::ACCEPT.as_str())) .and(path!("key" / String / String).and(warp::path::end())) + .and(warp::query()) .and(session::build()) .and_then(delete_one); // Specify route @@ -157,6 +164,7 @@ async fn create_all( output: String, table: String, body: Bytes, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -174,6 +182,7 @@ async fn create_all( let vars = map! { String::from("table") => Value::from(table), String::from("data") => data, + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { @@ -195,6 +204,7 @@ async fn create_all( async fn delete_all( output: String, table: String, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -206,6 +216,7 @@ async fn delete_all( // Specify the request variables let vars = map! { String::from("table") => Value::from(table), + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { @@ -266,6 +277,7 @@ async fn create_one( table: String, id: String, body: Bytes, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -289,6 +301,7 @@ async fn create_one( String::from("table") => Value::from(table), String::from("id") => rid, String::from("data") => data, + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { @@ -312,6 +325,7 @@ async fn update_one( table: String, id: String, body: Bytes, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -335,6 +349,7 @@ async fn update_one( String::from("table") => Value::from(table), String::from("id") => rid, String::from("data") => data, + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { @@ -358,6 +373,7 @@ async fn modify_one( table: String, id: String, body: Bytes, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -381,6 +397,7 @@ async fn modify_one( String::from("table") => Value::from(table), String::from("id") => rid, String::from("data") => data, + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { @@ -403,6 +420,7 @@ async fn delete_one( output: String, table: String, id: String, + params: Params, session: Session, ) -> Result { // Get the datastore reference @@ -420,6 +438,7 @@ async fn delete_one( let vars = map! { String::from("table") => Value::from(table), String::from("id") => rid, + => params.parse() }; // Execute the query and return the result match db.execute(sql, &session, Some(vars), opt.strict).await { diff --git a/src/net/mod.rs b/src/net/mod.rs index 2b7bf514..3406791e 100644 --- a/src/net/mod.rs +++ b/src/net/mod.rs @@ -7,6 +7,7 @@ mod index; mod key; mod log; mod output; +mod params; mod rpc; mod session; mod signin; diff --git a/src/net/params.rs b/src/net/params.rs new file mode 100644 index 00000000..9b5b2979 --- /dev/null +++ b/src/net/params.rs @@ -0,0 +1,24 @@ +use serde::Deserialize; +use std::collections::BTreeMap; +use surrealdb::sql::Value; + +#[derive(Default, Deserialize, Debug, Clone)] +pub struct Params { + #[serde(flatten)] + pub inner: BTreeMap, +} + +impl Params { + pub fn parse(self) -> BTreeMap { + self.into() + } +} + +impl From for BTreeMap { + fn from(v: Params) -> BTreeMap { + v.inner + .into_iter() + .map(|(k, v)| (k, surrealdb::sql::json(&v).unwrap_or_else(|_| Value::from(v)))) + .collect::>() + } +} diff --git a/src/net/sql.rs b/src/net/sql.rs index 7a394f71..8b16b680 100644 --- a/src/net/sql.rs +++ b/src/net/sql.rs @@ -2,6 +2,7 @@ use crate::cli::CF; use crate::dbs::DB; use crate::err::Error; use crate::net::output; +use crate::net::params::Params; use crate::net::session; use bytes::Bytes; use futures::{SinkExt, StreamExt}; @@ -22,6 +23,7 @@ pub fn config() -> impl Filter(http::header::ACCEPT.as_str())) .and(warp::body::content_length_limit(MAX)) .and(warp::body::bytes()) + .and(warp::query()) .and(session::build()) .and_then(handler); // Set sock method @@ -36,6 +38,7 @@ pub fn config() -> impl Filter Result { // Get a database reference @@ -45,7 +48,7 @@ async fn handler( // Convert the received sql query let sql = std::str::from_utf8(&sql).unwrap(); // Execute the received sql query - match db.execute(sql, &session, None, opt.strict).await { + match db.execute(sql, &session, params.parse().into(), opt.strict).await { // Convert the response to JSON Ok(res) => match output.as_ref() { "application/json" => Ok(output::json(&res)),