Improve RPC method return types (#1384)

This commit is contained in:
Rushmore Mushambi 2022-10-20 00:54:41 +02:00 committed by GitHub
parent c098fe3380
commit f0eaf2bd19
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 102 additions and 103 deletions

View file

@ -571,6 +571,10 @@ impl Value {
matches!(self, Value::Object(_)) matches!(self, Value::Object(_))
} }
pub fn is_number(&self) -> bool {
matches!(self, Value::Number(_))
}
pub fn is_int(&self) -> bool { pub fn is_int(&self) -> bool {
matches!(self, Value::Number(Number::Int(_))) matches!(self, Value::Number(Number::Int(_)))
} }

View file

@ -13,7 +13,7 @@ use surrealdb::sql::Value;
use surrealdb::Auth; use surrealdb::Auth;
use surrealdb::Session; use surrealdb::Session;
pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error> { pub async fn signin(session: &mut Session, vars: Object) -> Result<Value, Error> {
// Parse the specified variables // Parse the specified variables
let ns = vars.get("NS").or_else(|| vars.get("ns")); let ns = vars.get("NS").or_else(|| vars.get("ns"));
let db = vars.get("DB").or_else(|| vars.get("db")); let db = vars.get("DB").or_else(|| vars.get("db"));
@ -26,9 +26,7 @@ pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error
let db = db.to_strand().as_string(); let db = db.to_strand().as_string();
let sc = sc.to_strand().as_string(); let sc = sc.to_strand().as_string();
// Attempt to signin to specified scope // Attempt to signin to specified scope
let res = super::signin::sc(session, ns, db, sc, vars).await?; super::signin::sc(session, ns, db, sc, vars).await
// Return the result to the client
Ok(res)
} }
(Some(ns), Some(db), None) => { (Some(ns), Some(db), None) => {
// Get the provided user and pass // Get the provided user and pass
@ -44,9 +42,7 @@ pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error
let user = user.to_strand().as_string(); let user = user.to_strand().as_string();
let pass = pass.to_strand().as_string(); let pass = pass.to_strand().as_string();
// Attempt to signin to database // Attempt to signin to database
let res = super::signin::db(session, ns, db, user, pass).await?; super::signin::db(session, ns, db, user, pass).await
// Return the result to the client
Ok(res)
} }
// There is no username or password // There is no username or password
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
@ -65,9 +61,7 @@ pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error
let user = user.to_strand().as_string(); let user = user.to_strand().as_string();
let pass = pass.to_strand().as_string(); let pass = pass.to_strand().as_string();
// Attempt to signin to namespace // Attempt to signin to namespace
let res = super::signin::ns(session, ns, user, pass).await?; super::signin::ns(session, ns, user, pass).await
// Return the result to the client
Ok(res)
} }
// There is no username or password // There is no username or password
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
@ -85,9 +79,7 @@ pub async fn signin(session: &mut Session, vars: Object) -> Result<String, Error
let user = user.to_strand().as_string(); let user = user.to_strand().as_string();
let pass = pass.to_strand().as_string(); let pass = pass.to_strand().as_string();
// Attempt to signin to namespace // Attempt to signin to namespace
let res = super::signin::su(session, user, pass).await?; super::signin::su(session, user, pass).await
// Return the result to the client
Ok(res)
} }
// There is no username or password // There is no username or password
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
@ -103,7 +95,7 @@ pub async fn sc(
db: String, db: String,
sc: String, sc: String,
vars: Object, vars: Object,
) -> Result<String, Error> { ) -> Result<Value, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Get local copy of options // Get local copy of options
@ -160,7 +152,7 @@ pub async fn sc(
// Check the authentication token // Check the authentication token
match enc { match enc {
// The auth token was created successfully // The auth token was created successfully
Ok(tk) => Ok(tk), Ok(tk) => Ok(tk.into()),
// There was an error creating the token // There was an error creating the token
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
} }
@ -187,7 +179,7 @@ pub async fn db(
db: String, db: String,
user: String, user: String,
pass: String, pass: String,
) -> Result<String, Error> { ) -> Result<Value, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Create a new readonly transaction // Create a new readonly transaction
@ -223,7 +215,7 @@ pub async fn db(
// Check the authentication token // Check the authentication token
match enc { match enc {
// The auth token was created successfully // The auth token was created successfully
Ok(tk) => Ok(tk), Ok(tk) => Ok(tk.into()),
// There was an error creating the token // There was an error creating the token
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
} }
@ -242,7 +234,7 @@ pub async fn ns(
ns: String, ns: String,
user: String, user: String,
pass: String, pass: String,
) -> Result<String, Error> { ) -> Result<Value, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Create a new readonly transaction // Create a new readonly transaction
@ -276,7 +268,7 @@ pub async fn ns(
// Check the authentication token // Check the authentication token
match enc { match enc {
// The auth token was created successfully // The auth token was created successfully
Ok(tk) => Ok(tk), Ok(tk) => Ok(tk.into()),
// There was an error creating the token // There was an error creating the token
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
} }
@ -290,14 +282,14 @@ pub async fn ns(
} }
} }
pub async fn su(session: &mut Session, user: String, pass: String) -> Result<String, Error> { pub async fn su(session: &mut Session, user: String, pass: String) -> Result<Value, Error> {
// Get the config options // Get the config options
let opts = CF.get().unwrap(); let opts = CF.get().unwrap();
// Attempt to verify the root user // Attempt to verify the root user
if let Some(root) = &opts.pass { if let Some(root) = &opts.pass {
if user == opts.user && &pass == root { if user == opts.user && &pass == root {
session.au = Arc::new(Auth::Kv); session.au = Arc::new(Auth::Kv);
return Ok(String::from("")); return Ok(Value::None);
} }
} }
// The specified user login does not exist // The specified user login does not exist

View file

@ -11,7 +11,7 @@ use surrealdb::sql::Value;
use surrealdb::Auth; use surrealdb::Auth;
use surrealdb::Session; use surrealdb::Session;
pub async fn signup(session: &mut Session, vars: Object) -> Result<String, Error> { pub async fn signup(session: &mut Session, vars: Object) -> Result<Value, Error> {
// Parse the specified variables // Parse the specified variables
let ns = vars.get("NS").or_else(|| vars.get("ns")); let ns = vars.get("NS").or_else(|| vars.get("ns"));
let db = vars.get("DB").or_else(|| vars.get("db")); let db = vars.get("DB").or_else(|| vars.get("db"));
@ -24,9 +24,7 @@ pub async fn signup(session: &mut Session, vars: Object) -> Result<String, Error
let db = db.to_strand().as_string(); let db = db.to_strand().as_string();
let sc = sc.to_strand().as_string(); let sc = sc.to_strand().as_string();
// Attempt to signin to specified scope // Attempt to signin to specified scope
let res = super::signup::sc(session, ns, db, sc, vars).await?; super::signup::sc(session, ns, db, sc, vars).await
// Return the result to the client
Ok(res)
} }
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
} }
@ -38,7 +36,7 @@ pub async fn sc(
db: String, db: String,
sc: String, sc: String,
vars: Object, vars: Object,
) -> Result<String, Error> { ) -> Result<Value, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Get local copy of options // Get local copy of options
@ -95,7 +93,7 @@ pub async fn sc(
// Create the authentication token // Create the authentication token
match enc { match enc {
// The auth token was created successfully // The auth token was created successfully
Ok(tk) => Ok(tk), Ok(tk) => Ok(tk.into()),
// There was an error creating the token // There was an error creating the token
_ => Err(Error::InvalidAuth), _ => Err(Error::InvalidAuth),
} }

View file

@ -9,9 +9,10 @@ use crate::net::session;
use crate::net::LOG; use crate::net::LOG;
use crate::rpc::args::Take; use crate::rpc::args::Take;
use crate::rpc::paths::{ID, METHOD, PARAMS}; use crate::rpc::paths::{ID, METHOD, PARAMS};
use crate::rpc::res;
use crate::rpc::res::Failure; use crate::rpc::res::Failure;
use crate::rpc::res::Response;
use futures::{SinkExt, StreamExt}; use futures::{SinkExt, StreamExt};
use serde::Serialize;
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::sync::Arc; use std::sync::Arc;
use surrealdb::channel; use surrealdb::channel;
@ -127,24 +128,24 @@ impl Rpc {
// Convert the message // Convert the message
let str = match msg.to_str() { let str = match msg.to_str() {
Ok(v) => v, Ok(v) => v,
_ => return Response::failure(None, Failure::INTERNAL_ERROR).send(chn).await, _ => return res::failure(None, Failure::INTERNAL_ERROR).send(chn).await,
}; };
// Parse the request // Parse the request
let req = match surrealdb::sql::json(str) { let req = match surrealdb::sql::json(str) {
Ok(v) if v.is_some() => v, Ok(v) if v.is_some() => v,
_ => return Response::failure(None, Failure::PARSE_ERROR).send(chn).await, _ => return res::failure(None, Failure::PARSE_ERROR).send(chn).await,
}; };
// Fetch the 'id' argument // Fetch the 'id' argument
let id = match req.pick(&*ID) { let id = match req.pick(&*ID) {
Value::Uuid(v) => Some(v.to_raw()), v if v.is_uuid() || v.is_strand() || v.is_number() || v.is_none() || v.is_null() => {
Value::Strand(v) => Some(v.to_raw()), Some(v)
Value::Number(v) => Some(v.to_string()), }
_ => return Response::failure(None, Failure::INVALID_REQUEST).send(chn).await, _ => return res::failure(None, Failure::INVALID_REQUEST).send(chn).await,
}; };
// Fetch the 'method' argument // Fetch the 'method' argument
let method = match req.pick(&*METHOD) { let method = match req.pick(&*METHOD) {
Value::Strand(v) => v.to_raw(), Value::Strand(v) => v.to_raw(),
_ => return Response::failure(id, Failure::INVALID_REQUEST).send(chn).await, _ => return res::failure(id, Failure::INVALID_REQUEST).send(chn).await,
}; };
// Fetch the 'params' argument // Fetch the 'params' argument
let params = match req.pick(&*PARAMS) { let params = match req.pick(&*PARAMS) {
@ -153,99 +154,111 @@ impl Rpc {
}; };
// Match the method to a function // Match the method to a function
let res = match &method[..] { let res = match &method[..] {
"ping" => Ok(Value::True), "ping" => Ok(Value::None),
"info" => match params.len() { "info" => match params.len() {
0 => rpc.read().await.info().await, 0 => rpc.read().await.info().await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"use" => match params.take_two() { "use" => match params.take_two() {
(Value::Strand(ns), Value::Strand(db)) => rpc.write().await.yuse(ns, db).await, (Value::Strand(ns), Value::Strand(db)) => rpc.write().await.yuse(ns, db).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"signup" => match params.take_one() { "signup" => match params.take_one() {
Value::Object(v) => rpc.write().await.signup(v).await, Value::Object(v) => rpc.write().await.signup(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"signin" => match params.take_one() { "signin" => match params.take_one() {
Value::Object(v) => rpc.write().await.signin(v).await, Value::Object(v) => rpc.write().await.signin(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"invalidate" => match params.len() { "invalidate" => match params.len() {
0 => rpc.write().await.invalidate().await, 0 => rpc.write().await.invalidate().await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"authenticate" => match params.take_one() { "authenticate" => match params.take_one() {
Value::None => rpc.write().await.invalidate().await, Value::None => rpc.write().await.invalidate().await,
Value::Strand(v) => rpc.write().await.authenticate(v).await, Value::Strand(v) => rpc.write().await.authenticate(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"kill" => match params.take_one() { "kill" => match params.take_one() {
v if v.is_uuid() => rpc.read().await.kill(v).await, v if v.is_uuid() => rpc.read().await.kill(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"live" => match params.take_one() { "live" => match params.take_one() {
v if v.is_strand() => rpc.read().await.live(v).await, v if v.is_strand() => rpc.read().await.live(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"let" => match params.take_two() { "let" => match params.take_two() {
(Value::Strand(s), v) => rpc.write().await.set(s, v).await, (Value::Strand(s), v) => rpc.write().await.set(s, v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"set" => match params.take_two() { "set" => match params.take_two() {
(Value::Strand(s), v) => rpc.write().await.set(s, v).await, (Value::Strand(s), v) => rpc.write().await.set(s, v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"query" => match params.take_two() { "query" => match params.take_two() {
(Value::Strand(s), o) if o.is_none() => rpc.read().await.query(s).await, (Value::Strand(s), o) if o.is_none() => {
(Value::Strand(s), Value::Object(o)) => rpc.read().await.query_with(s, o).await, let res = rpc.read().await.query(s).await;
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, return match res {
Ok(v) => res::success(id, v).send(chn).await,
Err(e) => res::failure(id, Failure::custom(e.to_string())).send(chn).await,
};
}
(Value::Strand(s), Value::Object(o)) => {
let res = rpc.read().await.query_with(s, o).await;
return match res {
Ok(v) => res::success(id, v).send(chn).await,
Err(e) => res::failure(id, Failure::custom(e.to_string())).send(chn).await,
};
}
_ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"select" => match params.take_one() { "select" => match params.take_one() {
v if v.is_thing() => rpc.read().await.select(v).await, v if v.is_thing() => rpc.read().await.select(v).await,
v if v.is_strand() => rpc.read().await.select(v).await, v if v.is_strand() => rpc.read().await.select(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"create" => match params.take_two() { "create" => match params.take_two() {
(v, o) if v.is_thing() && o.is_none() => rpc.read().await.create(v, None).await, (v, o) if v.is_thing() && o.is_none() => rpc.read().await.create(v, None).await,
(v, o) if v.is_strand() && o.is_none() => rpc.read().await.create(v, None).await, (v, o) if v.is_strand() && o.is_none() => rpc.read().await.create(v, None).await,
(v, o) if v.is_thing() && o.is_object() => rpc.read().await.create(v, o).await, (v, o) if v.is_thing() && o.is_object() => rpc.read().await.create(v, o).await,
(v, o) if v.is_strand() && o.is_object() => rpc.read().await.create(v, o).await, (v, o) if v.is_strand() && o.is_object() => rpc.read().await.create(v, o).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"update" => match params.take_two() { "update" => match params.take_two() {
(v, o) if v.is_thing() && o.is_none() => rpc.read().await.update(v, None).await, (v, o) if v.is_thing() && o.is_none() => rpc.read().await.update(v, None).await,
(v, o) if v.is_strand() && o.is_none() => rpc.read().await.update(v, None).await, (v, o) if v.is_strand() && o.is_none() => rpc.read().await.update(v, None).await,
(v, o) if v.is_thing() && o.is_object() => rpc.read().await.update(v, o).await, (v, o) if v.is_thing() && o.is_object() => rpc.read().await.update(v, o).await,
(v, o) if v.is_strand() && o.is_object() => rpc.read().await.update(v, o).await, (v, o) if v.is_strand() && o.is_object() => rpc.read().await.update(v, o).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"change" => match params.take_two() { "change" => match params.take_two() {
(v, o) if v.is_thing() && o.is_none() => rpc.read().await.change(v, None).await, (v, o) if v.is_thing() && o.is_none() => rpc.read().await.change(v, None).await,
(v, o) if v.is_strand() && o.is_none() => rpc.read().await.change(v, None).await, (v, o) if v.is_strand() && o.is_none() => rpc.read().await.change(v, None).await,
(v, o) if v.is_thing() && o.is_object() => rpc.read().await.change(v, o).await, (v, o) if v.is_thing() && o.is_object() => rpc.read().await.change(v, o).await,
(v, o) if v.is_strand() && o.is_object() => rpc.read().await.change(v, o).await, (v, o) if v.is_strand() && o.is_object() => rpc.read().await.change(v, o).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"modify" => match params.take_two() { "modify" => match params.take_two() {
(v, o) if v.is_thing() && o.is_array() => rpc.read().await.modify(v, o).await, (v, o) if v.is_thing() && o.is_array() => rpc.read().await.modify(v, o).await,
(v, o) if v.is_strand() && o.is_array() => rpc.read().await.modify(v, o).await, (v, o) if v.is_strand() && o.is_array() => rpc.read().await.modify(v, o).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"delete" => match params.take_one() { "delete" => match params.take_one() {
v if v.is_thing() => rpc.read().await.delete(v).await, v if v.is_thing() => rpc.read().await.delete(v).await,
v if v.is_strand() => rpc.read().await.delete(v).await, v if v.is_strand() => rpc.read().await.delete(v).await,
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
"version" => match params.len() { "version" => match params.len() {
0 => Ok(format!("{}-{}", PKG_NAME, *PKG_VERS).into()), 0 => Ok(format!("{}-{}", PKG_NAME, *PKG_VERS).into()),
_ => return Response::failure(id, Failure::INVALID_PARAMS).send(chn).await, _ => return res::failure(id, Failure::INVALID_PARAMS).send(chn).await,
}, },
_ => return Response::failure(id, Failure::METHOD_NOT_FOUND).send(chn).await, _ => return res::failure(id, Failure::METHOD_NOT_FOUND).send(chn).await,
}; };
// Return the final response // Return the final response
match res { match res {
Ok(v) => Response::success(id, v).send(chn).await, Ok(v) => res::success(id, v).send(chn).await,
Err(e) => Response::failure(id, Failure::custom(e.to_string())).send(chn).await, Err(e) => res::failure(id, Failure::custom(e.to_string())).send(chn).await,
} }
} }
@ -260,17 +273,11 @@ impl Rpc {
} }
async fn signup(&mut self, vars: Object) -> Result<Value, Error> { async fn signup(&mut self, vars: Object) -> Result<Value, Error> {
crate::iam::signup::signup(&mut self.session, vars) crate::iam::signup::signup(&mut self.session, vars).await.map_err(Into::into)
.await
.map(Into::into)
.map_err(Into::into)
} }
async fn signin(&mut self, vars: Object) -> Result<Value, Error> { async fn signin(&mut self, vars: Object) -> Result<Value, Error> {
crate::iam::signin::signin(&mut self.session, vars) crate::iam::signin::signin(&mut self.session, vars).await.map_err(Into::into)
.await
.map(Into::into)
.map_err(Into::into)
} }
async fn invalidate(&mut self) -> Result<Value, Error> { async fn invalidate(&mut self) -> Result<Value, Error> {
@ -369,7 +376,7 @@ impl Rpc {
// Methods for querying // Methods for querying
// ------------------------------ // ------------------------------
async fn query(&self, sql: Strand) -> Result<Value, Error> { async fn query(&self, sql: Strand) -> Result<impl Serialize, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Get local copy of options // Get local copy of options
@ -378,13 +385,11 @@ impl Rpc {
let var = Some(self.vars.clone()); let var = Some(self.vars.clone());
// Execute the query on the database // Execute the query on the database
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?; let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
// Extract the first query result
let res = res.into_iter().collect::<Vec<Value>>().into();
// Return the result to the client // Return the result to the client
Ok(res) Ok(res)
} }
async fn query_with(&self, sql: Strand, mut vars: Object) -> Result<Value, Error> { async fn query_with(&self, sql: Strand, mut vars: Object) -> Result<impl Serialize, Error> {
// Get a database reference // Get a database reference
let kvs = DB.get().unwrap(); let kvs = DB.get().unwrap();
// Get local copy of options // Get local copy of options
@ -393,8 +398,6 @@ impl Rpc {
let var = Some(mrg! { vars.0, &self.vars }); let var = Some(mrg! { vars.0, &self.vars });
// Execute the query on the database // Execute the query on the database
let res = kvs.execute(&sql, &self.session, var, opt.strict).await?; let res = kvs.execute(&sql, &self.session, var, opt.strict).await?;
// Extract the first query result
let res = res.into_iter().collect::<Vec<Value>>().into();
// Return the result to the client // Return the result to the client
Ok(res) Ok(res)
} }

View file

@ -57,11 +57,11 @@ async fn handler(
Ok(Value::Object(vars)) => match crate::iam::signin::signin(&mut session, vars).await { Ok(Value::Object(vars)) => match crate::iam::signin::signin(&mut session, vars).await {
// Authentication was successful // Authentication was successful
Ok(v) => match output.as_deref() { Ok(v) => match output.as_deref() {
Some("application/json") => Ok(output::json(&Success::new(v))), Some("application/json") => Ok(output::json(&Success::new(v.as_string()))),
Some("application/cbor") => Ok(output::cbor(&Success::new(v))), Some("application/cbor") => Ok(output::cbor(&Success::new(v.as_string()))),
Some("application/msgpack") => Ok(output::pack(&Success::new(v))), Some("application/msgpack") => Ok(output::pack(&Success::new(v.as_string()))),
Some("text/plain") => Ok(output::text(v)), Some("text/plain") => Ok(output::text(v.as_string())),
None => Ok(output::text(v)), None => Ok(output::text(v.as_string())),
// An incorrect content-type was requested // An incorrect content-type was requested
_ => Err(warp::reject::custom(Error::InvalidType)), _ => Err(warp::reject::custom(Error::InvalidType)),
}, },

View file

@ -57,11 +57,11 @@ async fn handler(
Ok(Value::Object(vars)) => match crate::iam::signup::signup(&mut session, vars).await { Ok(Value::Object(vars)) => match crate::iam::signup::signup(&mut session, vars).await {
// Authentication was successful // Authentication was successful
Ok(v) => match output.as_deref() { Ok(v) => match output.as_deref() {
Some("application/json") => Ok(output::json(&Success::new(v))), Some("application/json") => Ok(output::json(&Success::new(v.as_string()))),
Some("application/cbor") => Ok(output::cbor(&Success::new(v))), Some("application/cbor") => Ok(output::cbor(&Success::new(v.as_string()))),
Some("application/msgpack") => Ok(output::pack(&Success::new(v))), Some("application/msgpack") => Ok(output::pack(&Success::new(v.as_string()))),
Some("text/plain") => Ok(output::text(v)), Some("text/plain") => Ok(output::text(v.as_string())),
None => Ok(output::text(v)), None => Ok(output::text(v.as_string())),
// An incorrect content-type was requested // An incorrect content-type was requested
_ => Err(warp::reject::custom(Error::InvalidType)), _ => Err(warp::reject::custom(Error::InvalidType)),
}, },

View file

@ -5,41 +5,27 @@ use surrealdb::sql::Value;
use warp::ws::Message; use warp::ws::Message;
#[derive(Serialize)] #[derive(Serialize)]
enum Content { enum Content<T> {
#[serde(rename = "result")] #[serde(rename = "result")]
Success(Value), Success(T),
#[serde(rename = "error")] #[serde(rename = "error")]
Failure(Failure), Failure(Failure),
} }
#[derive(Serialize)] #[derive(Serialize)]
pub struct Response { pub struct Response<T> {
id: Option<String>, id: Option<Value>,
#[serde(flatten)] #[serde(flatten)]
content: Content, content: Content<T>,
} }
impl Response { impl<T: Serialize> Response<T> {
// Send the response to the channel // Send the response to the channel
pub async fn send(self, chn: Sender<Message>) { pub async fn send(self, chn: Sender<Message>) {
let res = serde_json::to_string(&self).unwrap(); let res = serde_json::to_string(&self).unwrap();
let res = Message::text(res); let res = Message::text(res);
let _ = chn.send(res).await; let _ = chn.send(res).await;
} }
// Create a JSON RPC result response
pub fn success(id: Option<String>, val: Value) -> Response {
Response {
id,
content: Content::Success(val),
}
}
// Create a JSON RPC failure response
pub fn failure(id: Option<String>, err: Failure) -> Response {
Response {
id,
content: Content::Failure(err),
}
}
} }
#[derive(Clone, Debug, Serialize)] #[derive(Clone, Debug, Serialize)]
@ -84,3 +70,19 @@ impl Failure {
} }
} }
} }
// Create a JSON RPC result response
pub fn success<S: Serialize>(id: Option<Value>, val: S) -> Response<S> {
Response {
id,
content: Content::Success(val),
}
}
// Create a JSON RPC failure response
pub fn failure(id: Option<Value>, err: Failure) -> Response<Value> {
Response {
id,
content: Content::Failure(err),
}
}