From 246fcc704621d7c9626c990ded29b82abab47c8b Mon Sep 17 00:00:00 2001 From: metamuffin Date: Sat, 5 Aug 2023 18:57:41 +0200 Subject: move admin interface --- server/src/import.rs | 6 +- server/src/routes/mod.rs | 18 ++-- server/src/routes/ui/account/admin.rs | 154 ---------------------------------- server/src/routes/ui/account/mod.rs | 1 - server/src/routes/ui/admin/mod.rs | 154 ++++++++++++++++++++++++++++++++++ server/src/routes/ui/layout.rs | 9 +- server/src/routes/ui/mod.rs | 3 +- 7 files changed, 171 insertions(+), 174 deletions(-) delete mode 100644 server/src/routes/ui/account/admin.rs create mode 100644 server/src/routes/ui/admin/mod.rs (limited to 'server/src') diff --git a/server/src/import.rs b/server/src/import.rs index 872681f..9ffab48 100644 --- a/server/src/import.rs +++ b/server/src/import.rs @@ -7,11 +7,7 @@ use crate::{database::Database, federation::Federation, CONF}; use anyhow::{anyhow, bail, Context, Ok}; use async_recursion::async_recursion; use base64::Engine; -use futures::{ - future::join_all, - stream::{FuturesOrdered, FuturesUnordered}, - StreamExt, -}; +use futures::{stream::FuturesUnordered, StreamExt}; use jellyclient::Session; use jellycommon::{AssetLocation, MediaSource, Node, NodePrivate, RemoteImportOptions}; use log::{debug, error, info}; diff --git a/server/src/routes/mod.rs b/server/src/routes/mod.rs index d6e25b6..1490290 100644 --- a/server/src/routes/mod.rs +++ b/server/src/routes/mod.rs @@ -17,14 +17,14 @@ use std::fs::File; use stream::r_stream; use ui::{ account::{ - admin::{ - r_account_admin_dashboard, r_account_admin_import, r_account_admin_invite, - r_account_admin_remove_invite, r_account_admin_remove_user, - }, r_account_login, r_account_login_post, r_account_logout, r_account_logout_post, r_account_register, r_account_register_post, settings::{r_account_settings, r_account_settings_post}, }, + admin::{ + r_admin_dashboard, r_admin_import, r_admin_invite, r_admin_remove_invite, + r_admin_remove_user, + }, assets::r_item_assets, browser::r_all_items, error::{r_api_catch, r_catch}, @@ -99,11 +99,11 @@ pub fn build_rocket( r_account_register_post, r_account_logout, r_account_logout_post, - r_account_admin_dashboard, - r_account_admin_invite, - r_account_admin_remove_user, - r_account_admin_remove_invite, - r_account_admin_import, + r_admin_dashboard, + r_admin_invite, + r_admin_remove_user, + r_admin_remove_invite, + r_admin_import, r_account_settings, r_account_settings_post, r_api_version, diff --git a/server/src/routes/ui/account/admin.rs b/server/src/routes/ui/account/admin.rs deleted file mode 100644 index f1520b7..0000000 --- a/server/src/routes/ui/account/admin.rs +++ /dev/null @@ -1,154 +0,0 @@ -/* - 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 -*/ -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("/account/admin/dashboard")] -pub fn r_account_admin_dashboard( - session: Session, - database: &State, -) -> MyResult> { - if !session.user.admin { - Err(anyhow!("you not admin"))? - } - admin_dashboard(database, None) -} - -pub fn admin_dashboard<'a>( - database: &Database, - flash: Option>, -) -> MyResult> { - // TODO this doesnt scale, pagination! - let users = database.user.iter().collect::, _>>()?; - 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() } - h2 { "Library" } - form[method="POST", action=uri!(r_account_admin_import())] { - input[type="submit", value="(Re-)Import Library"]; - } - h2 { "Invitations" } - form[method="POST", action=uri!(r_account_admin_invite())] { - input[type="submit", value="Generate new invite code"]; - } - ul { @for t in &invites { - li { - form[method="POST", action=uri!(r_account_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_account_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("/account/admin/generate_invite")] -pub fn r_account_admin_invite( - session: Session, - database: &State, -) -> MyResult> { - if !session.user.admin { - Err(anyhow!("you not admin"))? - } - - let i = format!("{}", rand::thread_rng().gen::()); - database.invite.insert(&i, &())?; - - admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))) -} - -#[derive(FromForm)] -pub struct DeleteUser { - name: String, -} - -#[post("/account/admin/remove_user", data = "
")] -pub fn r_account_admin_remove_user( - session: Session, - database: &State, - form: Form, -) -> MyResult> { - 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("/account/admin/remove_invite", data = "")] -pub fn r_account_admin_remove_invite( - session: Session, - database: &State, - form: Form, -) -> MyResult> { - 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("/account/admin/import")] -pub async fn r_account_admin_import( - session: Session, - database: &State, - federation: &State, -) -> MyResult> { - 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())), - ), - ) -} diff --git a/server/src/routes/ui/account/mod.rs b/server/src/routes/ui/account/mod.rs index c04e29a..6bdf65a 100644 --- a/server/src/routes/ui/account/mod.rs +++ b/server/src/routes/ui/account/mod.rs @@ -3,7 +3,6 @@ which is licensed under the GNU Affero General Public License (version 3); see /COPYING. Copyright (C) 2023 metamuffin */ -pub mod admin; pub mod session; pub mod settings; 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 +*/ +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, +) -> MyResult> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + admin_dashboard(database, None) +} + +pub fn admin_dashboard<'a>( + database: &Database, + flash: Option>, +) -> MyResult> { + // TODO this doesnt scale, pagination! + let users = database.user.iter().collect::, _>>()?; + 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() } + 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, +) -> MyResult> { + if !session.user.admin { + Err(anyhow!("you not admin"))? + } + + let i = format!("{}", rand::thread_rng().gen::()); + database.invite.insert(&i, &())?; + + admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))) +} + +#[derive(FromForm)] +pub struct DeleteUser { + name: String, +} + +#[post("/admin/remove_user", data = "")] +pub fn r_admin_remove_user( + session: Session, + database: &State, + form: Form, +) -> MyResult> { + 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 = "")] +pub fn r_admin_remove_invite( + session: Session, + database: &State, + form: Form, +) -> MyResult> { + 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, + federation: &State, +) -> MyResult> { + 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())), + ), + ) +} diff --git a/server/src/routes/ui/layout.rs b/server/src/routes/ui/layout.rs index 7e51e5c..9a29df6 100644 --- a/server/src/routes/ui/layout.rs +++ b/server/src/routes/ui/layout.rs @@ -6,10 +6,11 @@ use crate::{ routes::ui::{ account::{ - admin::rocket_uri_macro_r_account_admin_dashboard, rocket_uri_macro_r_account_login, - rocket_uri_macro_r_account_logout, rocket_uri_macro_r_account_register, - session::Session, settings::rocket_uri_macro_r_account_settings, + rocket_uri_macro_r_account_login, rocket_uri_macro_r_account_logout, + rocket_uri_macro_r_account_register, session::Session, + settings::rocket_uri_macro_r_account_settings, }, + admin::rocket_uri_macro_r_admin_dashboard, browser::rocket_uri_macro_r_all_items, node::rocket_uri_macro_r_library_node, }, @@ -45,7 +46,7 @@ markup::define! { @if let Some(session) = session { span { "Logged in as " } span.username { @session.user.display_name } " " @if session.user.admin { - a[href=uri!(r_account_admin_dashboard())] { "Administration" } " " + a[href=uri!(r_admin_dashboard())] { "Administration" } " " } a[href=uri!(r_account_settings())] { "Settings" } " " a[href=uri!(r_account_logout())] { "Log out" } diff --git a/server/src/routes/ui/mod.rs b/server/src/routes/ui/mod.rs index 5fad2b7..7acc02a 100644 --- a/server/src/routes/ui/mod.rs +++ b/server/src/routes/ui/mod.rs @@ -22,6 +22,8 @@ use std::{ use tokio::{fs::File, io::AsyncRead}; pub mod account; +pub mod admin; +pub mod assets; pub mod browser; pub mod error; pub mod home; @@ -29,7 +31,6 @@ pub mod layout; pub mod node; pub mod player; pub mod style; -pub mod assets; pub struct HtmlTemplate<'a>(pub markup::DynRender<'a>); -- cgit v1.2.3-70-g09d2