From 17f46ce71d80f265e9899be918c41165906f1abe Mon Sep 17 00:00:00 2001 From: SadlyNotSappho Date: Tue, 13 Feb 2024 14:55:21 -0800 Subject: [PATCH] finish admin panel --- src/main.rs | 91 ++++++++++++++++++++++++++++----------------- src/tables.rs | 33 +++++++++------- web/adminpanel.html | 56 ++++++++++++++++++++++++++-- 3 files changed, 129 insertions(+), 51 deletions(-) diff --git a/src/main.rs b/src/main.rs index a3b193c..120eabf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -77,7 +77,13 @@ async fn account(mut db: Connection, cookies: &CookieJar<'_>) -> String { match token { Some(t) => { match User::get_by_token(&mut db, t).await { - Some(user) => format!("Username: {}\nAdmin: {}\nMake Posts: {}\nComment: {}", user.username, user.admin, user.make_posts, user.comment), + Some(user) => format!( + "Username: {}\nAdmin: {}\nMake Posts: {}\nComment: {}", + user.username, + user.admin, + user.make_posts, + user.comment + ), None => "User doesn't exist.".to_string() } }, @@ -140,7 +146,7 @@ async fn adminpanel(mut db: Connection, cookies: &CookieJar<'_>) -> RawHtml< Some(user) => match user.admin { true => { RawHtml( - fs::read_to_string("/srv/web/adminpanel.html").unwrap() + fs::read_to_string("/srv/web/adminpanel.html").unwrap().replace("{{username}}", &user.username[..]) ) }, false => RawHtml(fs::read_to_string("/srv/web/invalidperms.html").unwrap()) @@ -157,7 +163,7 @@ async fn adminpanel(mut db: Connection, cookies: &CookieJar<'_>) -> RawHtml< #[derive(Deserialize, Serialize)] #[serde(crate = "rocket::serde")] struct ApiPermsResult { - perms: Result + perms: Result } #[derive(Deserialize, Serialize)] #[serde(crate = "rocket::serde")] @@ -167,36 +173,52 @@ struct Perms{ comment: bool } #[get("/perms/")] -async fn api_perms(mut db: Connection, username: String) -> Json { - match User::get_by_username(&mut db, &username).await { - Some(user) => { - Json(ApiPermsResult { - perms: Ok(Perms { - admin: user.admin, - make_posts: user.make_posts, - comment: user.comment - })}) - }, - None => { - Json(ApiPermsResult { perms: Err(false) }) - } - } +async fn api_perms(mut db: Connection, username: String, cookies: &CookieJar<'_>) -> Json { +match cookies.get_private("token") { + Some(t) => { + match User::get_by_token(&mut db, t).await { + Some(user) => { + match user.admin { + true => { + match User::get_by_username(&mut db, &username).await { + Some(user) => { + Json(ApiPermsResult { + perms: Ok(Perms { + admin: user.admin, + make_posts: user.make_posts, + comment: user.comment + }) + }) + }, + None => { + Json(ApiPermsResult { perms: Err("User doesn't exist".to_string()) }) + } + } + }, + false => {Json(ApiPermsResult { perms: Err("You don't have the permission to do this".to_string())})} + } + }, + None => {Json(ApiPermsResult { perms: Err("Invalid token".to_string())})}, + }}, + None => {Json(ApiPermsResult { perms: Err("Not logged in".to_string())})} + } + } #[derive(Deserialize)] #[serde(crate = "rocket::serde")] -struct ToggleRole { +struct TogglePerms { perm: String, value: bool, username: String } -#[post("/togglerole", data = "")] -async fn togglerole( +#[post("/toggleperms", data = "")] +async fn toggleperms( mut db: Connection, - info: Json, + info: Json, cookies: &CookieJar<'_>, -) -> &'static str { +) -> String { match cookies.get_private("token") { Some(t) => { match User::get_by_token(&mut db, t).await { @@ -206,38 +228,39 @@ async fn togglerole( match User::get_by_username(&mut db, &info.username).await { Some(toggled_user) => { if toggled_user.username == user.username && info.perm == "admin".to_string() { - "You can't toggle your own admin status" + "You can't change your own admin status".to_string() } else { let admin_username = std::env::var("ADMIN_USERNAME").expect("set ADMIN_USERNAME env var"); if toggled_user.username == admin_username { - "You can't change the system admin's perms." + "You can't change the system admin's perms.".to_string() } else { if info.perm == "admin" && user.username != admin_username { - "You can't toggle other people's admin status." + "You can't change other people's admin status.".to_string() } else { // how deep is this shit // i counted. 12. // NOW we can actually do the thing :D - match toggled_user.set_role(db, &info.perm, &info.value).await { - Ok(_) => "Done", - Err(_) => "Couldn't update the user's role." - } + let res = match toggled_user.set_role(&mut db, &info.perm, &info.value).await { + Ok(_) => "Done".to_string(), + Err(why) => format!("Couldn't update the user's role: {why}") + }; + res } } } }, - None => "The user you're trying to toggle perms for doesn't exist." + None => "The user you're trying to toggle perms for doesn't exist.".to_string() } }, false => { - "You aren't an admin." + "You aren't an admin.".to_string() } } }, - None => "Invalid user" + None => "Invalid user".to_string() } }, - None => "Not logged in" + None => "Not logged in".to_string() } } @@ -316,7 +339,7 @@ async fn main() { .attach(AdHoc::on_ignite("DB Migrations", migrate)) .mount( "/", - routes![login_page, login, logout, createuser, createuser_page, account, adminpanel, togglerole], + routes![login_page, login, logout, createuser, createuser_page, account, adminpanel, toggleperms], ) .mount("/api", routes![api_perms]) .mount("/css", FileServer::from("/srv/web/css")) diff --git a/src/tables.rs b/src/tables.rs index 98b01cf..d0f81ff 100644 --- a/src/tables.rs +++ b/src/tables.rs @@ -55,7 +55,7 @@ impl Post { } } } -#[derive(FromRow)] +#[derive(FromRow, Debug)] pub struct User { pub id: i32, pub username: String, @@ -170,21 +170,28 @@ impl User { pub async fn set_role( &self, - mut db: Connection, + db: &mut Connection, role: &String, value: &bool, ) -> Result { - match db - .fetch_one( - sqlx::query("UPDATE users SET $1 = $2 WHERE id = $3") - .bind(role) - .bind(value) - .bind(self.id), - ) - .await - { - Ok(_) => Ok("Succesfully updated role.".to_string()), - Err(why) => Err(why.to_string()), + let mut sql = String::from("UPDATE users SET {{perm}} = $1 WHERE id = $2"); + if role == "admin" { + sql = sql.replace("{{perm}}", "admin"); + } else if role == "make_posts" { + sql = sql.replace("{{perm}}", "make_posts"); + } else if role == &"comment".to_string() { + sql = sql.replace("{{perm}}", "comment"); + } + if sql.contains("{{perm}}") { + Err("Invalid role.".to_string()) + } else { + match db + .execute(sqlx::query(&sql[..]).bind(value).bind(self.id)) + .await + { + Ok(_) => Ok("Succesfully updated role.".to_string()), + Err(why) => Err(why.to_string()), + } } } } diff --git a/web/adminpanel.html b/web/adminpanel.html index 9dfd52f..edd34d3 100644 --- a/web/adminpanel.html +++ b/web/adminpanel.html @@ -17,7 +17,7 @@ struct ToggleRole {
- perms toggle + Welcome, {{username}}. Please select a user to modify.
@@ -48,28 +48,76 @@ struct ToggleRole { const user = JSON.parse(await (await fetch(`/api/perms/${username}`)).text()).perms if (user.Ok) { + // set checked + document.getElementById("admin-toggle").checked = user.Ok.admin + document.getElementById("make-post-toggle").checked = user.Ok.make_posts + document.getElementById("comment-toggle").checked = user.Ok.comment + + // toggle views document.querySelector(".toggle-form").style.display = "block" document.getElementById("username-form").style.display = "none" document.getElementById("load-button").style.display = "none" - document.getElementById("data").innerHTML = `Username: ${username}` - document.getElementById("admin-toggle").checked = user.Ok.admin + // update text at top + document.getElementById("data").innerHTML = `You're logged in as {{username}}. You're modifying ${username}.` + } else { alert("User doesn't exist.") } break } - // TODO: imlpement these, server handles perm checks case "admin-toggle": { // admin toggle + let username = document.getElementById("username").value; + const update = await (await fetch("/toggleperms", { + method: "POST", + header: {"Content-Type": "application/json"}, + body: JSON.stringify( + { + username: username, + perm: "admin", + value: document.getElementById("admin-toggle").checked + } + ) + })).text() + if (update == "Done") {document.getElementById("admin-toggle").checked = !document.getElementById("admin-toggle").checked} + alert(update) break } case "make-post-toggle": { // make post toggle + let username = document.getElementById("username").value; + const update = await (await fetch("/toggleperms", { + method: "POST", + header: {"Content-Type": "application/json"}, + body: JSON.stringify( + { + username: username, + perm: "make_posts", + value: document.getElementById("make-post-toggle").checked + } + ) + })).text() + if (update == "Done") {document.getElementById("make-post-toggle").checked = !document.getElementById("make-post-toggle").checked} + alert(update) break } case "comment-toggle": { // comment toggle + let username = document.getElementById("username").value; + const update = await (await fetch("/toggleperms", { + method: "POST", + header: {"Content-Type": "application/json"}, + body: JSON.stringify( + { + username: username, + perm: "comment", + value: document.getElementById("comment-toggle").checked + } + ) + })).text() + if (update == "Done") {document.getElementById("comment-toggle").checked = !document.getElementById("comment-toggle").checked} + alert(update) break } }