diff options
author | metamuffin <metamuffin@disroot.org> | 2023-08-05 18:57:41 +0200 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-08-05 22:45:30 +0200 |
commit | 246fcc704621d7c9626c990ded29b82abab47c8b (patch) | |
tree | 561c96b0c86f30f49e41ec408d616f109d93dd43 /server/src/routes/ui/admin/mod.rs | |
parent | b22f639737e2ee0152969e2106869538a3009ce6 (diff) | |
download | jellything-246fcc704621d7c9626c990ded29b82abab47c8b.tar jellything-246fcc704621d7c9626c990ded29b82abab47c8b.tar.bz2 jellything-246fcc704621d7c9626c990ded29b82abab47c8b.tar.zst |
move admin interface
Diffstat (limited to 'server/src/routes/ui/admin/mod.rs')
-rw-r--r-- | server/src/routes/ui/admin/mod.rs | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/server/src/routes/ui/admin/mod.rs b/server/src/routes/ui/admin/mod.rs new file mode 100644 index 0000000..0775423 --- /dev/null +++ b/server/src/routes/ui/admin/mod.rs @@ -0,0 +1,154 @@ +/* + This file is part of jellything (https://codeberg.org/metamuffin/jellything) + which is licensed under the GNU Affero General Public License (version 3); see /COPYING. + Copyright (C) 2023 metamuffin <metamuffin.org> +*/ +use crate::{ + database::Database, + federation::Federation, + import::import, + routes::ui::{ + account::session::Session, + error::MyResult, + layout::{DynLayoutPage, FlashDisplay, LayoutPage}, + }, + uri, +}; +use anyhow::anyhow; +use rand::Rng; +use rocket::{form::Form, get, post, FromForm, State}; +use std::time::Instant; + +#[get("/admin/dashboard")] +pub fn r_admin_dashboard( + session: Session, + database: &State<Database>, +) -> MyResult<DynLayoutPage<'static>> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + admin_dashboard(database, None) +} + +pub fn admin_dashboard<'a>( + database: &Database, + flash: Option<MyResult<String>>, +) -> MyResult<DynLayoutPage<'a>> { + // TODO this doesnt scale, pagination! + let users = database.user.iter().collect::<Result<Vec<_>, _>>()?; + let invites = database.invite.iter().collect::<Result<Vec<_>, _>>()?; + let flash = flash.map(|f| f.map_err(|e| format!("{e:?}"))); + + Ok(LayoutPage { + title: "Admin Dashboard".to_string(), + content: markup::new! { + h1 { "Admin Panel" } + @FlashDisplay { flash: flash.clone() } + h2 { "Library" } + form[method="POST", action=uri!(r_admin_import())] { + input[type="submit", value="(Re-)Import Library"]; + } + h2 { "Invitations" } + form[method="POST", action=uri!(r_admin_invite())] { + input[type="submit", value="Generate new invite code"]; + } + ul { @for t in &invites { + li { + form[method="POST", action=uri!(r_admin_remove_invite())] { + span { @t.0 } + input[type="text", name="invite", value=&t.0, hidden]; + input[type="submit", value="Invalidate"]; + } + } + }} + h2 { "Users" } + ul { @for (_, u) in &users { + li { form[method="POST", action=uri!(r_admin_remove_user())] { + span { @format!("{:?}", u.display_name) " (" @u.name ")" } + input[type="text", name="name", value=&u.name, hidden]; + input[type="submit", value="Remove(!)"]; + }} + }} + }, + ..Default::default() + }) +} + +#[post("/admin/generate_invite")] +pub fn r_admin_invite( + session: Session, + database: &State<Database>, +) -> MyResult<DynLayoutPage<'static>> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + + let i = format!("{}", rand::thread_rng().gen::<u128>()); + database.invite.insert(&i, &())?; + + admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))) +} + +#[derive(FromForm)] +pub struct DeleteUser { + name: String, +} + +#[post("/admin/remove_user", data = "<form>")] +pub fn r_admin_remove_user( + session: Session, + database: &State<Database>, + form: Form<DeleteUser>, +) -> MyResult<DynLayoutPage<'static>> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + database + .user + .remove(&form.name)? + .ok_or(anyhow!("user did not exist"))?; + + admin_dashboard(database, Some(Ok("User removed".into()))) +} + +#[derive(FromForm)] +pub struct DeleteInvite { + invite: String, +} + +#[post("/admin/remove_invite", data = "<form>")] +pub fn r_admin_remove_invite( + session: Session, + database: &State<Database>, + form: Form<DeleteInvite>, +) -> MyResult<DynLayoutPage<'static>> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + database + .invite + .remove(&form.invite)? + .ok_or(anyhow!("invite did not exist"))?; + + admin_dashboard(database, Some(Ok("Invite invalidated".into()))) +} + +#[post("/admin/import")] +pub async fn r_admin_import( + session: Session, + database: &State<Database>, + federation: &State<Federation>, +) -> MyResult<DynLayoutPage<'static>> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + let t = Instant::now(); + let r = import(&database, &federation).await; + admin_dashboard( + &database, + Some( + r.map_err(|e| e.into()) + .map(|_| format!("Import successful; took {:?}", t.elapsed())), + ), + ) +} |