/* 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 */ pub mod log; pub mod user; use super::account::session::AdminSession; use crate::{ database::Database, routes::ui::{ admin::log::rocket_uri_macro_r_admin_log, error::MyResult, layout::{DynLayoutPage, FlashDisplay, LayoutPage}, }, uri, }; use anyhow::anyhow; use jellybase::{federation::Federation, CONF}; use jellyimport::import; use rand::Rng; use rocket::{form::Form, get, post, FromForm, State}; use std::time::Instant; use user::rocket_uri_macro_r_admin_users; #[get("/admin/dashboard")] pub fn r_admin_dashboard( _session: AdminSession, database: &State, ) -> MyResult> { admin_dashboard(database, None) } pub fn admin_dashboard<'a>( database: &Database, flash: Option>, ) -> MyResult> { let invites = database.invite.iter().collect::, _>>()?; 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() } ul { li{a[href=uri!(r_admin_log(true))] { "Server Log (Warnings only)" }} li{a[href=uri!(r_admin_log(false))] { "Server Log (Full) " }} } h2 { "Library" } form[method="POST", action=uri!(r_admin_import())] { input[type="submit", value="(Re-)Import Library"]; } form[method="POST", action=uri!(r_admin_delete_cache())] { input[type="submit", value="Delete Cache"]; } h2 { "Users" } p { a[href=uri!(r_admin_users())] "Manage Users" } 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"]; } } }} }, ..Default::default() }) } #[post("/admin/generate_invite")] pub fn r_admin_invite( _session: AdminSession, database: &State, ) -> MyResult> { let i = format!("{}", rand::thread_rng().gen::()); database.invite.insert(&i, &())?; admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))) } #[derive(FromForm)] pub struct DeleteInvite { invite: String, } #[post("/admin/remove_invite", data = "
")] pub fn r_admin_remove_invite( session: AdminSession, database: &State, form: Form, ) -> MyResult> { drop(session); 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: AdminSession, database: &State, federation: &State, ) -> MyResult> { drop(session); 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())), ), ) } #[post("/admin/delete_cache")] pub async fn r_admin_delete_cache( session: AdminSession, database: &State, ) -> MyResult> { drop(session); let t = Instant::now(); let r = tokio::fs::remove_dir_all(&CONF.cache_path).await; tokio::fs::create_dir(&CONF.cache_path).await?; admin_dashboard( &database, Some( r.map_err(|e| e.into()) .map(|_| format!("Cache deleted; took {:?}", t.elapsed())), ), ) }