diff --git a/src/error.rs b/src/error.rs index 78a0e0a..a51e8da 100644 --- a/src/error.rs +++ b/src/error.rs @@ -28,6 +28,9 @@ pub enum ChorusError { // Auth required AuthRequired, + // Bad request + BadRequest(String), + // Event is banned BannedEvent, @@ -139,6 +142,7 @@ impl std::fmt::Display for ChorusError { match self { ChorusError::AuthFailure(s) => write!(f, "AUTH failure: {s}"), ChorusError::AuthRequired => write!(f, "AUTH required"), + ChorusError::BadRequest(s) => write!(f, "Bad Request: {s}"), ChorusError::BannedEvent => write!(f, "Event is banned"), ChorusError::BannedUser => write!(f, "User is banned"), ChorusError::Base64Decode(e) => write!(f, "{e}"), @@ -209,6 +213,7 @@ impl ChorusError { match self { ChorusError::AuthFailure(_) => 0.25, ChorusError::AuthRequired => 0.0, + ChorusError::BadRequest(_) => 0.1, ChorusError::BannedEvent => 0.1, ChorusError::BannedUser => 0.2, ChorusError::Base64Decode(_) => 0.0, diff --git a/src/web/management/mod.rs b/src/web/management/mod.rs index 03f4601..4e92ea7 100644 --- a/src/web/management/mod.rs +++ b/src/web/management/mod.rs @@ -1,10 +1,11 @@ -use crate::error::Error; +use crate::error::{ChorusError, Error}; +use crate::globals::GLOBALS; use crate::ip::HashedPeer; use http_body_util::Full; use hyper::body::{Bytes, Incoming}; use hyper::{Request, Response, StatusCode}; -use serde_json::{json, Value}; - +use pocket_types::Pubkey; +use serde_json::{json, Map, Value}; mod auth; pub async fn handle( @@ -22,13 +23,95 @@ pub async fn handle( } }; - println!("command was {}", command); + let obj = match command.as_object() { + Some(o) => o, + None => return fail("Command was not a JSON object"), + }; + let method = match obj.get("method") { + Some(m) => match m.as_str() { + Some(s) => s.to_owned(), + None => return fail("Method not a string"), + }, + None => return fail("Method missing"), + }; + + match &*method { + "supportedmethods" => { + return respond( + json!({ + "result": ["allowpubkey", "banpubkey", "supportedmethods"] + }), + StatusCode::OK, + ) + } + + // Pubkeys + "banpubkey" => match get_pubkey_param(obj) { + Ok(pk) => { + crate::mark_pubkey_approval(GLOBALS.store.get().unwrap(), pk, false)?; + return worked(); + } + Err(e) => return fail(&format!("{e}")), + }, + "allowpubkey" => match get_pubkey_param(obj) { + Ok(pk) => { + crate::mark_pubkey_approval(GLOBALS.store.get().unwrap(), pk, true)?; + return worked(); + } + Err(e) => return fail(&format!("{e}")), + }, + "listbannedpubkeys" => return fail(&format!("Unsupported method {}", method)), + "listallowedpubkeys" => return fail(&format!("Unsupported method {}", method)), + + // Events + "banevent" => return fail(&format!("Unsupported method {}", method)), + "listbannedevents" => return fail(&format!("Unsupported method {}", method)), + "allowevent" => return fail(&format!("Unsupported method {}", method)), + "listallowedevents" => return fail(&format!("Unsupported method {}", method)), + "listeventsneedingmoderation" => return fail(&format!("Unsupported method {}", method)), + + // Kinds + "allowkind" => return fail(&format!("Unsupported method {}", method)), + "disallowkind" => return fail(&format!("Unsupported method {}", method)), + "listbannedkinds" => return fail(&format!("Unsupported method {}", method)), + "listallowedkinds" => return fail(&format!("Unsupported method {}", method)), + + // IP addresses + "blockip" => return fail(&format!("Unsupported method {}", method)), + "unblockip" => return fail(&format!("Unsupported method {}", method)), + "listblockedips" => return fail(&format!("Unsupported method {}", method)), + + // Config + "changerelayname" => return fail(&format!("Unsupported method {}", method)), + "changerelaydescription" => return fail(&format!("Unsupported method {}", method)), + "changerelayicon" => return fail(&format!("Unsupported method {}", method)), + + _ => return fail(&format!("Unsupported method {}", method)), + } + + /* let result = json!({ "result": {}, "error": "The Management API is not yet implemented" }); respond(result, StatusCode::NOT_IMPLEMENTED) + */ +} + +fn fail(msg: &str) -> Result>, Error> { + let result = json!({ + "result": {}, + "error": msg + }); + respond(result, StatusCode::BAD_REQUEST) +} + +fn worked() -> Result>, Error> { + let result = json!({ + "result": {}, + }); + respond(result, StatusCode::OK) } fn respond(json: serde_json::Value, status: StatusCode) -> Result>, Error> { @@ -42,3 +125,18 @@ fn respond(json: serde_json::Value, status: StatusCode) -> Result) -> Result { + let pubkey_text = obj + .get("params") + .ok_or::(ChorusError::BadRequest("Params field missing".to_owned()).into())? + .as_array() + .ok_or::(ChorusError::BadRequest("Params not an array".to_owned()).into())? + .get(0) + .ok_or::(ChorusError::BadRequest("Missing pubkey parameter".to_owned()).into())? + .as_str() + .ok_or::( + ChorusError::BadRequest("Pubkey parameter is wrong type".to_owned()).into(), + )?; + Ok(Pubkey::read_hex(pubkey_text.as_bytes())?) +}