finish admin panel

This commit is contained in:
SadlyNotSappho 2024-02-13 14:55:21 -08:00
parent 2fb3edeb40
commit 17f46ce71d
3 changed files with 129 additions and 51 deletions

View File

@ -77,7 +77,13 @@ async fn account(mut db: Connection<Db>, cookies: &CookieJar<'_>) -> String {
match token { match token {
Some(t) => { Some(t) => {
match User::get_by_token(&mut db, t).await { 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() None => "User doesn't exist.".to_string()
} }
}, },
@ -140,7 +146,7 @@ async fn adminpanel(mut db: Connection<Db>, cookies: &CookieJar<'_>) -> RawHtml<
Some(user) => match user.admin { Some(user) => match user.admin {
true => { true => {
RawHtml( 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()) false => RawHtml(fs::read_to_string("/srv/web/invalidperms.html").unwrap())
@ -157,7 +163,7 @@ async fn adminpanel(mut db: Connection<Db>, cookies: &CookieJar<'_>) -> RawHtml<
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
struct ApiPermsResult { struct ApiPermsResult {
perms: Result<Perms, bool> perms: Result<Perms, String>
} }
#[derive(Deserialize, Serialize)] #[derive(Deserialize, Serialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
@ -167,7 +173,13 @@ struct Perms{
comment: bool comment: bool
} }
#[get("/perms/<username>")] #[get("/perms/<username>")]
async fn api_perms(mut db: Connection<Db>, username: String) -> Json<ApiPermsResult> { async fn api_perms(mut db: Connection<Db>, username: String, cookies: &CookieJar<'_>) -> Json<ApiPermsResult> {
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 { match User::get_by_username(&mut db, &username).await {
Some(user) => { Some(user) => {
Json(ApiPermsResult { Json(ApiPermsResult {
@ -175,28 +187,38 @@ async fn api_perms(mut db: Connection<Db>, username: String) -> Json<ApiPermsRes
admin: user.admin, admin: user.admin,
make_posts: user.make_posts, make_posts: user.make_posts,
comment: user.comment comment: user.comment
})}) })
})
}, },
None => { None => {
Json(ApiPermsResult { perms: Err(false) }) 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)] #[derive(Deserialize)]
#[serde(crate = "rocket::serde")] #[serde(crate = "rocket::serde")]
struct ToggleRole { struct TogglePerms {
perm: String, perm: String,
value: bool, value: bool,
username: String username: String
} }
#[post("/togglerole", data = "<info>")] #[post("/toggleperms", data = "<info>")]
async fn togglerole( async fn toggleperms(
mut db: Connection<Db>, mut db: Connection<Db>,
info: Json<ToggleRole>, info: Json<TogglePerms>,
cookies: &CookieJar<'_>, cookies: &CookieJar<'_>,
) -> &'static str { ) -> String {
match cookies.get_private("token") { match cookies.get_private("token") {
Some(t) => { Some(t) => {
match User::get_by_token(&mut db, t).await { 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 { match User::get_by_username(&mut db, &info.username).await {
Some(toggled_user) => { Some(toggled_user) => {
if toggled_user.username == user.username && info.perm == "admin".to_string() { 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 { } else {
let admin_username = std::env::var("ADMIN_USERNAME").expect("set ADMIN_USERNAME env var"); let admin_username = std::env::var("ADMIN_USERNAME").expect("set ADMIN_USERNAME env var");
if toggled_user.username == admin_username { 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 { } else {
if info.perm == "admin" && user.username != admin_username { 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 { } else {
// how deep is this shit // how deep is this shit
// i counted. 12. // i counted. 12.
// NOW we can actually do the thing :D // NOW we can actually do the thing :D
match toggled_user.set_role(db, &info.perm, &info.value).await { let res = match toggled_user.set_role(&mut db, &info.perm, &info.value).await {
Ok(_) => "Done", Ok(_) => "Done".to_string(),
Err(_) => "Couldn't update the user's role." 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 => { 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)) .attach(AdHoc::on_ignite("DB Migrations", migrate))
.mount( .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("/api", routes![api_perms])
.mount("/css", FileServer::from("/srv/web/css")) .mount("/css", FileServer::from("/srv/web/css"))

View File

@ -55,7 +55,7 @@ impl Post {
} }
} }
} }
#[derive(FromRow)] #[derive(FromRow, Debug)]
pub struct User { pub struct User {
pub id: i32, pub id: i32,
pub username: String, pub username: String,
@ -170,21 +170,28 @@ impl User {
pub async fn set_role( pub async fn set_role(
&self, &self,
mut db: Connection<Db>, db: &mut Connection<Db>,
role: &String, role: &String,
value: &bool, value: &bool,
) -> Result<String, String> { ) -> Result<String, 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 match db
.fetch_one( .execute(sqlx::query(&sql[..]).bind(value).bind(self.id))
sqlx::query("UPDATE users SET $1 = $2 WHERE id = $3")
.bind(role)
.bind(value)
.bind(self.id),
)
.await .await
{ {
Ok(_) => Ok("Succesfully updated role.".to_string()), Ok(_) => Ok("Succesfully updated role.".to_string()),
Err(why) => Err(why.to_string()), Err(why) => Err(why.to_string()),
} }
} }
}
} }

View File

@ -17,7 +17,7 @@ struct ToggleRole {
<body> <body>
<div id="data"> <div id="data">
perms toggle Welcome, {{username}}. Please select a user to modify.
</div> </div>
<form action="/toggleperms" method="post" class="permtoggle-form" id="permtoggle-form"> <form action="/toggleperms" method="post" class="permtoggle-form" id="permtoggle-form">
<div id="username-form"> <div id="username-form">
@ -48,28 +48,76 @@ struct ToggleRole {
const user = JSON.parse(await (await fetch(`/api/perms/${username}`)).text()).perms const user = JSON.parse(await (await fetch(`/api/perms/${username}`)).text()).perms
if (user.Ok) { 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.querySelector(".toggle-form").style.display = "block"
document.getElementById("username-form").style.display = "none" document.getElementById("username-form").style.display = "none"
document.getElementById("load-button").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 { } else {
alert("User doesn't exist.") alert("User doesn't exist.")
} }
break break
} }
// TODO: imlpement these, server handles perm checks
case "admin-toggle": { case "admin-toggle": {
// 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 break
} }
case "make-post-toggle": { case "make-post-toggle": {
// 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 break
} }
case "comment-toggle": { case "comment-toggle": {
// 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 break
} }
} }