diff --git a/json-api/db/src/neighbors.rs b/json-api/db/src/neighbors.rs index d211cb1..a922d06 100644 --- a/json-api/db/src/neighbors.rs +++ b/json-api/db/src/neighbors.rs @@ -1,19 +1,34 @@ use crate::Neighbor; use mysql_async::Result as SqlResult; -use mysql_async::{Pool, prelude::Queryable}; +use mysql_async::{params, Pool, prelude::Queryable}; use serde_json; -impl Neighbor { - pub async fn get_all(p: &Pool) -> SqlResult> { - let mut conn = p.get_conn().await?; - let q = "SELECT name, description, tags, url, wsurl FROM neighbors"; - type Types = (String, Option, String, String, Option); - let set: Vec = conn.exec_map(q, (), |(name, description, tags, url, wsurl): Types| { - let json: Vec = serde_json::from_str(tags.as_str()).unwrap_or(vec![]); - Neighbor { - name, description, tags: json, url, wsurl - } - }).await?; - Ok(set) - } +pub async fn get_all(p: &Pool) -> SqlResult> { + let mut conn = p.get_conn().await?; + let q = "SELECT name, description, tags, url, wsurl FROM neighbors"; + type Types = (String, Option, String, String, Option); + let set: Vec = conn.exec_map(q, (), |(name, description, tags, url, wsurl): Types| { + let json: Vec = serde_json::from_str(tags.as_str()).unwrap_or(vec![]); + Neighbor { + name, description, tags: json, url, wsurl + } + }).await?; + Ok(set) +} + +pub async fn add_neighbor(p: &Pool, url: &str, wsurl: &str, name: &str, desc: &str, tags:&str) -> SqlResult<()> { + // Note we assume that the tags field has been verified as proper valid json prior to + // writing it to the db + let mut conn = p.get_conn().await?; + let q = "INSERT INTO neighbors(url, wsurl, name, description, tags) + VALUES(:url, :wsurl, :name, :description, :tags)"; + let sqlparams = params!{ + "url"=> url, + "wsurl"=>wsurl, + "name"=>name, + "desc"=>desc, + "tags"=>tags + }; + conn.exec_drop(q, sqlparams).await?; + Ok(()) } diff --git a/json-api/src/main.rs b/json-api/src/main.rs index 66588b1..199eb5a 100644 --- a/json-api/src/main.rs +++ b/json-api/src/main.rs @@ -90,6 +90,7 @@ async fn route_dispatcher( (GET, routes::META) => meta::server_meta(resp).await, /* Federated Routes */ (GET, routes::GET_NEIGHBORS) => meta::server_neighbors(pool, resp).await, + (POST, routes::ADD_NEIGHBOR) => meta::add_neighbor(pool, resp, params).await, _ => { println!("[HTTP]\tNOT FOUND: {}: {}", meth, path); *resp.status_mut() = StatusCode::NOT_FOUND @@ -206,8 +207,8 @@ fn init_config() -> Result<(), Box> { pub wss_hmac_path: String, pub name: String, pub description: Option, - pub public_url: String, - pub public_ws_url: String, + pub url: String, + pub wsurl: String, pub tags: Option> } use std::fs::File; @@ -229,15 +230,13 @@ fn init_config() -> Result<(), Box> { set_var("SERVER_DESCRIPTION", fields.description.unwrap_or("".into())); - set_var("PUBLIC_URL", fields.public_url); - set_var("PUBLIC_WS_URL", fields.public_ws_url); - // NOTE: the debug print actually prints out what looks to be valid json - // so we're just going to leverage that for passing this bs around - let tags_json = match fields.tags { - Some(t) => format!("{:?}", t), - None => format!("[]") - }; - set_var("SERVER_TAGS", tags_json); + set_var("PUBLIC_URL", fields.url); + set_var("PUBLIC_WS_URL", fields.wsurl); + + // Mega cheesy way of forcing config initialization + if meta::get_config().tags.len() == 0 { + eprintln!("[API] [WARN] No tags have been set", ); + } Ok(()) } diff --git a/json-api/src/meta.rs b/json-api/src/meta.rs index 0f14cbd..b5df7d8 100644 --- a/json-api/src/meta.rs +++ b/json-api/src/meta.rs @@ -69,3 +69,30 @@ pub async fn server_neighbors(p: &Pool, response: &mut Response) { } } + +pub async fn add_neighbor(p: &Pool, response: &mut Response, params: HashMap) { + let url = params.get("url"); + let wsurl = params.get("wsurl"); + let name = params.get("name"); + let desc = params.get("description"); + let tags = params.get("tags"); + + // If any parameter is missing then fail away quickly + if url.is_none() || wsurl.is_none() || name.is_none() || desc.is_none() || tags.is_none() { + *response.status_mut() = StatusCode::BAD_REQUEST; + return; + } + // Safe unwrap because of the check above + let url = url.unwrap(); + let wsurl = wsurl.unwrap(); + let name = name.unwrap(); + let desc = desc.unwrap(); + let tags = tags.unwrap(); + match db::neighbors::add_neighbor(p, url, wsurl, name, desc, tags).await { + Ok(()) => {}, + Err(e) => { + eprintln!("{}", e); + *response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR; + } + } +} diff --git a/json-api/src/routes.rs b/json-api/src/routes.rs index 9f8f672..d391ffe 100644 --- a/json-api/src/routes.rs +++ b/json-api/src/routes.rs @@ -25,7 +25,8 @@ pub const SET_PERMS_BY_ADMIN: Rstr = "/admin/setpermisions"; // @requires per pub const SET_NEW_ADMIN: Rstr = "/owner/newadmin"; // @requiers: owner perms // Server -> Server Routes -pub const GET_NEIGHBORS: Rstr = "/neighbors/list"; // @requires: none @note must be a member for this list +pub const GET_NEIGHBORS: Rstr = "/neighbor/list"; // @requires: none @note must be a member for this list +pub const ADD_NEIGHBOR: Rstr = "/neighbor/add"; // @requires: perm::add_neighbor pub fn is_open(path: &str) -> bool { return path.starts_with("/join") || path.starts_with("/meta"); @@ -33,6 +34,7 @@ pub fn is_open(path: &str) -> bool { pub fn requires_perms(path: &str) -> bool { return match path { + /* These routes _don't_ require any permissions */ AUTH_LOGIN | META | CHANNELS_LIST | GET_MYSELF | GET_NEIGHBORS => false, _ => true }