diff --git a/src/main.rs b/src/main.rs index afcf5fb..74c6746 100644 --- a/src/main.rs +++ b/src/main.rs @@ -293,26 +293,37 @@ async fn get_admin( db: Arc>, ) -> Result, Error> { let authorised = is_authorised(req, db.clone(), 3).await; - if authorised { - return not_found().await; + if !authorised { + return get_page(&req, "/unauthorised", db).await; } - if path == "/admin" { - return get_page(req, path, db).await; + match path { + "/admin" => { + get_page(req, path, db).await}, + "/admin/users" => { + let pool = db.clone().lock().unwrap().clone(); + let users = sqlx::query!(r#"SELECT id, username, permissions FROM users"#) + .fetch_all(&pool) + .await + .unwrap(); + let users: Vec<(i64, String, i64)> = users + .iter() + .map(|x| (x.id, x.username.clone(), x.permissions)) + .collect(); + let stringed = serde_json::to_string(&users).unwrap_or("".to_string()); + Ok(Response::builder().body(Body::new(stringed)).unwrap()) + }, + "/admin/players" => { + let pool = db.clone().lock().unwrap().clone(); + let players = sqlx::query!(r#"SELECT id, name FROM players"#) + .fetch_all(&pool) + .await + .unwrap(); + let players: Vec = players.iter().map(|x| Player{id: x.id, name: x.name.clone()}).collect(); + let stringed = serde_json::to_string(&players).unwrap_or("".to_string()); + Ok(Response::builder().body(Body::new(stringed)).unwrap()) + } + _ => not_found().await, } - if path == "/admin/users" { - let pool = db.clone().lock().unwrap().clone(); - let users = sqlx::query!(r#"SELECT username, permissions FROM users"#) - .fetch_all(&pool) - .await - .unwrap(); - let users: Vec<(String, i64)> = users - .iter() - .map(|x| (x.username.clone(), x.permissions)) - .collect(); - let stringed = serde_json::to_string(&users).unwrap_or("".to_string()); - return Ok(Response::builder().body(Body::new(stringed)).unwrap()); - } - not_found().await } async fn post(req: Request, db: Arc>) -> Result, Error> { @@ -369,19 +380,92 @@ async fn post_admin( db: Arc>, ) -> Result, Error> { let authorised = is_authorised(&req, db.clone(), 3).await; - if authorised { + if !authorised { return get_page(&req, "/unauthorised", db).await; } let path = req.uri().path(); match path { - "/admin/post/user" => { - req_json::(req).await; + "/admin/edit/user" => { + match req_json::(req).await { + Some(Value::Object(user)) => { + let username = user.get("username"); + let permissions = user.get("permissions"); + let id = user.get("id"); + if username.is_none() || permissions.is_none() || id.is_none() { + return bad_request().await; + } + let pool = db.clone().lock().unwrap().clone(); + let mut conn = pool.acquire().await.unwrap(); + let username = username.unwrap().as_str().unwrap(); + let permissions = permissions.unwrap(); + let id = id.unwrap(); + let _ = sqlx::query!(r#"UPDATE users SET username = ?1, permissions = ?2 WHERE id = ?3"#, username, permissions, id).execute(&mut *conn).await; + ok().await + }, + _ => {bad_request().await} + } + }, + "/admin/delete/user" => { + match req_json::(req).await { + Some(Value::Object(user)) => { + let id = user.get("id"); + if id.is_none() { + return bad_request().await; + } + let pool = db.clone().lock().unwrap().clone(); + let mut conn = pool.acquire().await.unwrap(); + let id = id.unwrap().as_i64().unwrap(); + let _ = sqlx::query!(r#"DELETE FROM users WHERE id = ?1"#, id).execute(&mut *conn).await; + ok().await + } + _ => {bad_request().await} + } + }, + "/admin/edit/player" => { + match req_json::(req).await { + Some(player) => { + let pool = db.clone().lock().unwrap().clone(); + let mut conn = pool.acquire().await.unwrap(); + let _ = sqlx::query!(r#"UPDATE players SET name = ?1 WHERE id = ?2"#, player.name, player.id).execute(&mut *conn).await; + ok().await + }, + _ => bad_request().await + } } - "/admin/post/vote" => {} - "/admin/post/player" => {} - _ => {} + "/admin/new/player" => { + match req_json::(req).await { + Some(Value::Object(player)) => { + let name = player.get("name"); + if name.is_none() { + return bad_request().await; + } + let pool = db.clone().lock().unwrap().clone(); + let mut conn = pool.acquire().await.unwrap(); + let name = name.unwrap().as_str().unwrap(); + let _ = sqlx::query!(r#"INSERT INTO players (name) VALUES (?1)"#, name).execute(&mut *conn).await; + ok().await + }, + _ => {bad_request().await} + } + }, + "/admin/delete/player" => { + match req_json::(req).await { + Some(Value::Object(player)) => { + let id = player.get("id"); + if id.is_none() { + return bad_request().await; + } + let pool = db.clone().lock().unwrap().clone(); + let mut conn = pool.acquire().await.unwrap(); + let id = id.unwrap().as_i64().unwrap(); + let _ = sqlx::query!(r#"DELETE FROM players WHERE id = ?1"#, id).execute(&mut *conn).await; + ok().await + } + _ => {bad_request().await} + } + } + _ => {bad_request().await} } - not_found().await } async fn login( @@ -391,17 +475,11 @@ async fn login( let body = req.into_body().collect().await; let data: Result = from_reader(body?.aggregate().reader()); if data.is_err() { - return Ok(Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::Empty) - .unwrap()); + return bad_request().await; } let data = data.unwrap(); if !check_username(&data.username) { - return Ok(Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::Empty) - .unwrap()); + return bad_request().await; } let pool = db.clone().lock().unwrap().clone(); let result = sqlx::query!(r#"SELECT * FROM users WHERE username=?1"#, data.username) @@ -415,7 +493,6 @@ async fn login( Ok(()) => { let date: DateTime = DateTime::from(SystemTime::now()); let date = date.checked_add_days(Days::new(7)).unwrap(); - // With server side rendering, redirect here to "/" Ok(Response::builder() .header( SET_COOKIE, @@ -435,16 +512,10 @@ async fn login( .body(Body::Empty) .unwrap()) } - Err(_) => Ok(Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::Empty) - .unwrap()), + Err(_) => bad_request().await, } } - Ok(None) => Ok(Response::builder() - .status(StatusCode::BAD_REQUEST) - .body(Body::Empty) - .unwrap()), + Ok(None) => bad_request().await, Err(_) => Ok(Response::builder() .status(StatusCode::INTERNAL_SERVER_ERROR) .body(Body::Empty) @@ -599,6 +670,13 @@ async fn not_found() -> Result, Error> { .unwrap()) } +async fn bad_request() -> Result, Error> { + Ok(Response::builder().status(StatusCode::BAD_REQUEST).body(Body::Empty).unwrap()) +} + +async fn ok() -> Result, Error> { + Ok(Response::builder().body(Body::Empty).unwrap()) +} async fn req_json(req: Request) -> Option where T: DeserializeOwned, diff --git a/static/html/admin.html b/static/html/admin.html index f5db6f6..6cca1a8 100644 --- a/static/html/admin.html +++ b/static/html/admin.html @@ -12,11 +12,13 @@

Users

+

id, username, permission

-

Votes

-
+

Players

+

id, name

+
\ No newline at end of file diff --git a/static/js/admin.js b/static/js/admin.js index 02117b8..bf8dbf1 100644 --- a/static/js/admin.js +++ b/static/js/admin.js @@ -4,19 +4,69 @@ async function run() { let usersDiv = document.getElementById("users"); for (let i = 0; i < users.length; i++) { let item = document.createElement("div"); + let id = document.createElement("p"); let username = document.createElement("input"); let permissions = document.createElement("input"); let edit = document.createElement("button"); + let del = document.createElement("button"); edit.textContent = "Edit"; - username.value = users[i][0]; - permissions.value = users[i][1]; + del.textContent = "Delete"; + id.textContent = users[i][0]; + username.value = users[i][1]; + permissions.value = users[i][2]; item.style.display = "flex"; - item.append(username, permissions, edit); + item.append(id, username, permissions, edit, del); usersDiv.appendChild(item); + edit.addEventListener("click", async () => { + await fetch("/admin/edit/user", {method: "POST", body: JSON.stringify({"id": users[i][0], "username": username.value, "permissions": parseInt(permissions.value)})}); + window.location.reload(); + }) + del.addEventListener("click", async () => { + await fetch("/admin/delete/user", {method:"POST", body: JSON.stringify({"id": users[i][0]})}); + window.location.reload(); + }) } -// let votes = await fetch("/admin/votes").then(r => r.json()); + let players = await fetch("/admin/players").then(r => r.json()); + let playersDiv = document.getElementById("players"); + for (let i=0; i { + await fetch("/admin/edit/player", {method: "POST", body: JSON.stringify({"id": players[i]["id"], "name": name.value})}); + window.location.reload(); + }) + del.addEventListener("click", async () => { + await fetch("/admin/delete/player", {method:"POST", body: JSON.stringify({"id": players[i]["id"]})}); + window.location.reload(); + }) + } + let newPlayer = document.createElement("button"); + newPlayer.textContent = "Add Player"; + newPlayer.addEventListener("click", () => { + let item = document.createElement("div"); + let name = document.createElement("input"); + let save = document.createElement("button"); + save.textContent = "Save"; + item.append(name, save); + playersDiv.appendChild(item); + save.addEventListener("click", async () => { + await fetch("/admin/new/player", {method:"POST", body: JSON.stringify({"name": name.value})}) + window.location.reload(); + }) + }) + playersDiv.parentNode.append(newPlayer); } let _ = run(); \ No newline at end of file