+ First pass of db backend and API handlers for badges module
It should be noted that /badge/update needs some more planning so 1 more commit is justified for it as some consideration must be taken for how individual badge permissions are going to be handled
This commit is contained in:
parent
4352c840ac
commit
2d1f9a37db
80
json-api/db/src/badges.rs
Normal file
80
json-api/db/src/badges.rs
Normal file
@ -0,0 +1,80 @@
|
||||
use crate::Badge;
|
||||
use mysql_async::prelude::Queryable;
|
||||
use mysql_async::{params, Pool, Result as SqlResult};
|
||||
use rand::RngCore;
|
||||
|
||||
pub async fn add(pool: &Pool, name: &str, color: u32, perms: u64) -> SqlResult<Badge>{
|
||||
// First gather the parameters required for the query
|
||||
let id = rand::rngs::OsRng.next_u64();
|
||||
|
||||
let mut conn = pool.get_conn().await?;
|
||||
let q = "INSERT INTO badges (id, name, color, permissions)
|
||||
VALUES(:id, :name, :color, :perms)";
|
||||
let sqlparams = params!{
|
||||
"id" => id,
|
||||
"name" => name,
|
||||
"color" => color,
|
||||
"perms" => perms
|
||||
};
|
||||
conn.exec_drop(q, sqlparams).await?;
|
||||
Ok(Badge{
|
||||
id,
|
||||
name: String::from(name),
|
||||
color,
|
||||
perms
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn delete(pool: &Pool, id: u64) -> SqlResult<u64> {
|
||||
let mut conn = pool.get_conn().await?;
|
||||
let q = "DELETE FROM badges WHERE id = :id";
|
||||
conn.exec_drop(q, params!{"id" => id}).await?;
|
||||
Ok(id)
|
||||
}
|
||||
|
||||
async fn get(pool: &Pool, id: u64) -> SqlResult<Option<Badge>> {
|
||||
let mut conn = pool.get_conn().await?;
|
||||
let q = "SELECT name, color, permissions FROM badges WHERE id = :id";
|
||||
let row: Option<(String, u32, u64)> = conn.exec_first(q, params!{ "id" => id}).await?;
|
||||
match row {
|
||||
Some(row) => {
|
||||
let b = Badge {
|
||||
id,
|
||||
name: row.0,
|
||||
color: row.1,
|
||||
perms: row.2,
|
||||
};
|
||||
Ok(Some(b))
|
||||
},
|
||||
None => Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update(pool: &Pool, badge: Badge) -> SqlResult<Option<Badge>> {
|
||||
// Ok(None) if that badge was not registered anywhere
|
||||
// Ok(Some(Badge)) if that badge was registered
|
||||
if let Ok(None) = get(pool, badge.id).await {
|
||||
return Ok(None);
|
||||
}
|
||||
|
||||
let q = "UPDATE badges SET name = :name, color = :color, permissions = :perms
|
||||
WHERE id = :id";
|
||||
let p = params! {
|
||||
"id" => badge.id,
|
||||
"name" => badge.name.clone(),
|
||||
"color" => badge.color,
|
||||
"perms" => badge.perms
|
||||
};
|
||||
let mut conn = pool.get_conn().await?;
|
||||
conn.exec_drop(q, p).await?;
|
||||
Ok(Some(badge))
|
||||
}
|
||||
|
||||
pub async fn list(pool: &Pool) -> SqlResult<Vec<Badge>> {
|
||||
let q = "SELECT id, name, color, permissions FROM badges";
|
||||
let mut conn = pool.get_conn().await?;
|
||||
let set: Vec<Badge> = conn.exec_map(q, (), |(id, name, color, perms)| {
|
||||
Badge { id, name, color, perms }
|
||||
}).await?;
|
||||
Ok(set)
|
||||
}
|
73
json-api/src/badges.rs
Normal file
73
json-api/src/badges.rs
Normal file
@ -0,0 +1,73 @@
|
||||
use crate::{db, qs_param, http::set_json_body};
|
||||
|
||||
use std::collections::HashMap;
|
||||
use mysql_async::Pool;
|
||||
use hyper::{Response, StatusCode, Body};
|
||||
use serde_json::json;
|
||||
|
||||
pub async fn new(p: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
||||
// Only name is really required the other two can default to white/
|
||||
let name = qs_param!(params, "badge_name", String);
|
||||
let perms = match qs_param!(params, "badge_perms", u64) {
|
||||
Some(perms) => perms,
|
||||
None => 0
|
||||
};
|
||||
let color = match qs_param!(params, "badge_color", u32) {
|
||||
Some(color) => color,
|
||||
None => 0xffffffff,
|
||||
};
|
||||
if let Some(name) = name {
|
||||
match db::badges::add(p, &name, color, perms).await {
|
||||
Ok(badge) => {
|
||||
set_json_body(response, json!({"badge": json!(badge)}));
|
||||
// TODO: add some rtc notification here
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("[HTTP][ERROR] /badge/new {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
};
|
||||
} else {
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn update(_p: &Pool, _response: &mut Response<Body>, _params: HashMap<String, String>) {
|
||||
/* TODO:
|
||||
* This handler could actually benefit from being split into multiple handlers
|
||||
* Concern: Permissions handling with is route could get ugly when handling updates to the
|
||||
* permissions flag in each badge which is why we may want a
|
||||
* /badge/update/color
|
||||
* /badge/update/name
|
||||
* /badge/update/permissions
|
||||
*/
|
||||
}
|
||||
|
||||
pub async fn delete(p: &Pool, response: &mut Response<Body>, params: HashMap<String, String>) {
|
||||
if let Some(id) = qs_param!(params, "badge_id", u64) {
|
||||
match db::badges::delete(p, id).await {
|
||||
Ok(id) => {
|
||||
// TODO: add rtc notification here
|
||||
println!("TODO remove me at some point {}", id);
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("[HTTP][ERROR] /badge/delete {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
*response.status_mut() = StatusCode::BAD_REQUEST;
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn list(p: &Pool, response: &mut Response<Body>) {
|
||||
match db::badges::list(p).await {
|
||||
Ok(badges) => {
|
||||
set_json_body(response, json!({"badges": json!(badges)}));
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("[HTTP][ERRO] /badge/list {}", e);
|
||||
*response.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user