diff options
author | metamuffin <metamuffin@disroot.org> | 2025-01-29 18:03:06 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2025-01-29 18:03:06 +0100 |
commit | db511d3fe50f05329615f718515fab1b80d9e06a (patch) | |
tree | 7969fea01be100cbe4385ad13a14940a987ac513 /server/src/routes/ui/admin | |
parent | 82e8a55a1496ae9132e13e7286fe1c0d57d586d3 (diff) | |
download | jellything-db511d3fe50f05329615f718515fab1b80d9e06a.tar jellything-db511d3fe50f05329615f718515fab1b80d9e06a.tar.bz2 jellything-db511d3fe50f05329615f718515fab1b80d9e06a.tar.zst |
no direct redb access
Diffstat (limited to 'server/src/routes/ui/admin')
-rw-r--r-- | server/src/routes/ui/admin/mod.rs | 170 | ||||
-rw-r--r-- | server/src/routes/ui/admin/user.rs | 67 |
2 files changed, 95 insertions, 142 deletions
diff --git a/server/src/routes/ui/admin/mod.rs b/server/src/routes/ui/admin/mod.rs index 1fba6c0..160999b 100644 --- a/server/src/routes/ui/admin/mod.rs +++ b/server/src/routes/ui/admin/mod.rs @@ -6,12 +6,9 @@ pub mod log; pub mod user; -use super::{ - account::session::AdminSession, - assets::{resolve_asset, AVIF_QUALITY, AVIF_SPEED}, -}; +use super::account::session::AdminSession; use crate::{ - database::DataAcid, + database::Database, routes::ui::{ admin::log::rocket_uri_macro_r_admin_log, error::MyResult, @@ -20,16 +17,7 @@ use crate::{ uri, }; use anyhow::{anyhow, Context}; -use humansize::{format_size, DECIMAL}; -use jellybase::{ - assetfed::AssetInner, - database::{ - redb::{ReadableTable, ReadableTableMetadata}, - tantivy::query::Bm25StatisticsProvider, - TableExt, T_INVITE, T_NODE, T_USER_NODE, - }, - CONF, -}; +use jellybase::CONF; use markup::DynRender; use rand::Rng; use rocket::{form::Form, get, post, FromForm, State}; @@ -40,28 +28,16 @@ use user::rocket_uri_macro_r_admin_users; #[get("/admin/dashboard")] pub async fn r_admin_dashboard( _session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, ) -> MyResult<DynLayoutPage<'static>> { admin_dashboard(database, None).await } pub async fn admin_dashboard<'a>( - database: &DataAcid, + database: &Database, flash: Option<MyResult<String>>, ) -> MyResult<DynLayoutPage<'a>> { - let invites = { - let txn = database.begin_read()?; - let table = txn.open_table(T_INVITE)?; - let i = table - .iter()? - .map(|a| { - let (x, _) = a.unwrap(); - x.value().to_owned() - }) - .collect::<Vec<_>>(); - drop(table); - i - }; + let invites = database.list_invites()?; let flash = flash.map(|f| f.map_err(|e| format!("{e:?}"))); // let last_import_err = IMPORT_ERRORS.read().await.to_owned(); @@ -129,11 +105,10 @@ pub async fn admin_dashboard<'a>( #[post("/admin/generate_invite")] pub async fn r_admin_invite( _session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, ) -> MyResult<DynLayoutPage<'static>> { let i = format!("{}", rand::rng().random::<u128>()); - T_INVITE.insert(database, &*i, ())?; - + database.create_invite(&i)?; admin_dashboard(database, Some(Ok(format!("Invite: {}", i)))).await } @@ -145,14 +120,13 @@ pub struct DeleteInvite { #[post("/admin/remove_invite", data = "<form>")] pub async fn r_admin_remove_invite( session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, form: Form<DeleteInvite>, ) -> MyResult<DynLayoutPage<'static>> { drop(session); - T_INVITE - .remove(database, form.invite.as_str())? - .ok_or(anyhow!("invite did not exist"))?; - + if !database.delete_invite(&form.invite)? { + Err(anyhow!("invite does not exist"))?; + }; admin_dashboard(database, Some(Ok("Invite invalidated".into()))).await } @@ -178,7 +152,7 @@ pub async fn r_admin_remove_invite( #[post("/admin/delete_cache")] pub async fn r_admin_delete_cache( session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, ) -> MyResult<DynLayoutPage<'static>> { drop(session); let t = Instant::now(); @@ -202,7 +176,7 @@ fn is_transcoding() -> bool { #[post("/admin/transcode_posters")] pub async fn r_admin_transcode_posters( session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, ) -> MyResult<DynLayoutPage<'static>> { drop(session); let _permit = SEM_TRANSCODING @@ -211,24 +185,25 @@ pub async fn r_admin_transcode_posters( let t = Instant::now(); - { - let txn = database.begin_read()?; - let nodes = txn.open_table(T_NODE)?; - for node in nodes.iter()? { - let (_, node) = node?; - if let Some(poster) = &node.value().0.poster { - let asset = AssetInner::deser(&poster.0)?; - if asset.is_federated() { - continue; - } - let source = resolve_asset(asset).await.context("resolving asset")?; - jellytranscoder::image::transcode(source, AVIF_QUALITY, AVIF_SPEED, 1024) - .await - .context("transcoding asset")?; - } - } - } - drop(_permit); + // TODO + // { + // let txn = database.begin_read()?; + // let nodes = txn.open_table(T_NODE)?; + // for node in nodes.iter()? { + // let (_, node) = node?; + // if let Some(poster) = &node.value().0.poster { + // let asset = AssetInner::deser(&poster.0)?; + // if asset.is_federated() { + // continue; + // } + // let source = resolve_asset(asset).await.context("resolving asset")?; + // jellytranscoder::image::transcode(source, AVIF_QUALITY, AVIF_SPEED, 1024) + // .await + // .context("transcoding asset")?; + // } + // } + // } + // drop(_permit); admin_dashboard( database, @@ -240,47 +215,48 @@ pub async fn r_admin_transcode_posters( .await } -fn db_stats(db: &DataAcid) -> anyhow::Result<DynRender> { - let txn = db.inner.begin_read()?; - let stats = [ - ("node", txn.open_table(T_NODE)?.stats()?), - ("user", txn.open_table(T_USER_NODE)?.stats()?), - ("user-node", txn.open_table(T_USER_NODE)?.stats()?), - ("invite", txn.open_table(T_INVITE)?.stats()?), - ]; +fn db_stats(_db: &Database) -> anyhow::Result<DynRender> { + // TODO + // let txn = db.inner.begin_read()?; + // let stats = [ + // ("node", txn.open_table(T_NODE)?.stats()?), + // ("user", txn.open_table(T_USER_NODE)?.stats()?), + // ("user-node", txn.open_table(T_USER_NODE)?.stats()?), + // ("invite", txn.open_table(T_INVITE)?.stats()?), + // ]; - let cache_stats = db.node_index.reader.searcher().doc_store_cache_stats(); - let ft_total_docs = db.node_index.reader.searcher().total_num_docs()?; + // let cache_stats = db.node_index.reader.searcher().doc_store_cache_stats(); + // let ft_total_docs = db.node_index.reader.searcher().total_num_docs()?; Ok(markup::new! { - h3 { "Key-Value-Store Statistics" } - table.border { - tbody { - tr { - th { "table name" } - th { "tree height" } - th { "stored bytes" } - th { "metadata bytes" } - th { "fragmented bytes" } - th { "branch pages" } - th { "leaf pages" } - } - @for (name, stats) in &stats { tr { - td { @name } - td { @stats.tree_height() } - td { @format_size(stats.stored_bytes(), DECIMAL) } - td { @format_size(stats.metadata_bytes(), DECIMAL) } - td { @format_size(stats.fragmented_bytes(), DECIMAL) } - td { @stats.branch_pages() } - td { @stats.leaf_pages() } - }} - } - } - h3 { "Search Engine Statistics" } - ul { - li { "Total documents: " @ft_total_docs } - li { "Cache misses: " @cache_stats.cache_misses } - li { "Cache hits: " @cache_stats.cache_hits } - } + // h3 { "Key-Value-Store Statistics" } + // table.border { + // tbody { + // tr { + // th { "table name" } + // th { "tree height" } + // th { "stored bytes" } + // th { "metadata bytes" } + // th { "fragmented bytes" } + // th { "branch pages" } + // th { "leaf pages" } + // } + // @for (name, stats) in &stats { tr { + // td { @name } + // td { @stats.tree_height() } + // td { @format_size(stats.stored_bytes(), DECIMAL) } + // td { @format_size(stats.metadata_bytes(), DECIMAL) } + // td { @format_size(stats.fragmented_bytes(), DECIMAL) } + // td { @stats.branch_pages() } + // td { @stats.leaf_pages() } + // }} + // } + // } + // h3 { "Search Engine Statistics" } + // ul { + // li { "Total documents: " @ft_total_docs } + // li { "Cache misses: " @cache_stats.cache_misses } + // li { "Cache hits: " @cache_stats.cache_hits } + // } }) } diff --git a/server/src/routes/ui/admin/user.rs b/server/src/routes/ui/admin/user.rs index 524f849..7ba6d4e 100644 --- a/server/src/routes/ui/admin/user.rs +++ b/server/src/routes/ui/admin/user.rs @@ -4,7 +4,7 @@ Copyright (C) 2025 metamuffin <metamuffin.org> */ use crate::{ - database::DataAcid, + database::Database, routes::ui::{ account::session::AdminSession, error::MyResult, @@ -13,36 +13,23 @@ use crate::{ uri, }; use anyhow::{anyhow, Context}; -use jellybase::database::{redb::ReadableTable, Ser, TableExt, T_USER}; use jellycommon::user::{PermissionSet, UserPermission}; use rocket::{form::Form, get, post, FromForm, FromFormField, State}; #[get("/admin/users")] pub fn r_admin_users( _session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, ) -> MyResult<DynLayoutPage<'static>> { user_management(database, None) } fn user_management<'a>( - database: &DataAcid, + database: &Database, flash: Option<MyResult<String>>, ) -> MyResult<DynLayoutPage<'a>> { // TODO this doesnt scale, pagination! - let users = { - let txn = database.begin_read()?; - let table = txn.open_table(T_USER)?; - let i = table - .iter()? - .map(|a| { - let (x, y) = a.unwrap(); - (x.value().to_owned(), y.value().0) - }) - .collect::<Vec<_>>(); - drop(table); - i - }; + let users = database.list_users()?; let flash = flash.map(|f| f.map_err(|e| format!("{e:?}"))); Ok(LayoutPage { @@ -51,7 +38,7 @@ fn user_management<'a>( h1 { "User Management" } @FlashDisplay { flash: flash.clone() } h2 { "All Users" } - ul { @for (_, u) in &users { + ul { @for u in &users { li { a[href=uri!(r_admin_user(&u.name))] { @format!("{:?}", u.display_name) " (" @u.name ")" } } @@ -64,19 +51,19 @@ fn user_management<'a>( #[get("/admin/user/<name>")] pub fn r_admin_user<'a>( _session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, name: &'a str, ) -> MyResult<DynLayoutPage<'a>> { manage_single_user(database, None, name.to_string()) } fn manage_single_user<'a>( - database: &DataAcid, + database: &Database, flash: Option<MyResult<String>>, name: String, ) -> MyResult<DynLayoutPage<'a>> { - let user = T_USER - .get(database, &*name)? + let user = database + .get_user(&name)? .ok_or(anyhow!("user does not exist"))?; let flash = flash.map(|f| f.map_err(|e| format!("{e:?}"))); @@ -152,31 +139,21 @@ pub enum GrantState { #[post("/admin/update_user_permission", data = "<form>")] pub fn r_admin_user_permission( session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, form: Form<UserPermissionForm>, ) -> MyResult<DynLayoutPage<'static>> { drop(session); let perm = serde_json::from_str::<UserPermission>(&form.permission) .context("parsing provided permission")?; - let txn = database.begin_write()?; - let mut users = txn.open_table(T_USER)?; - - let mut user = users - .get(&*form.name)? - .ok_or(anyhow!("user missing"))? - .value() - .0; - - match form.action { - GrantState::Grant => drop(user.permissions.0.insert(perm.clone(), true)), - GrantState::Revoke => drop(user.permissions.0.insert(perm.clone(), false)), - GrantState::Unset => drop(user.permissions.0.remove(&perm)), - } - - users.insert(&*form.name, Ser(user))?; - drop(users); - txn.commit()?; + database.update_user(&form.name, |user| { + match form.action { + GrantState::Grant => drop(user.permissions.0.insert(perm.clone(), true)), + GrantState::Revoke => drop(user.permissions.0.insert(perm.clone(), false)), + GrantState::Unset => drop(user.permissions.0.remove(&perm)), + } + Ok(()) + })?; manage_single_user( database, @@ -188,12 +165,12 @@ pub fn r_admin_user_permission( #[post("/admin/remove_user", data = "<form>")] pub fn r_admin_remove_user( session: AdminSession, - database: &State<DataAcid>, + database: &State<Database>, form: Form<DeleteUser>, ) -> MyResult<DynLayoutPage<'static>> { drop(session); - T_USER - .remove(database, form.name.as_str())? - .ok_or(anyhow!("user did not exist"))?; + if !database.delete_user(&form.name)? { + Err(anyhow!("user did not exist"))?; + } user_management(database, Some(Ok("User removed".into()))) } |