aboutsummaryrefslogtreecommitdiff
path: root/server
diff options
context:
space:
mode:
Diffstat (limited to 'server')
-rw-r--r--server/src/routes.rs8
-rw-r--r--server/src/ui/admin/mod.rs73
-rw-r--r--server/src/ui/admin/users.rs120
-rw-r--r--server/src/ui/mod.rs3
-rw-r--r--server/src/ui/user.rs28
5 files changed, 129 insertions, 103 deletions
diff --git a/server/src/routes.rs b/server/src/routes.rs
index 0df3aa7..f17952a 100644
--- a/server/src/routes.rs
+++ b/server/src/routes.rs
@@ -19,7 +19,8 @@ use crate::{
admin::{
import::{r_admin_import, r_admin_import_post, r_admin_import_stream},
log::{r_admin_log, r_admin_log_stream},
- r_admin_dashboard, r_admin_new_user, r_admin_users,
+ r_admin_dashboard,
+ users::{r_admin_new_user, r_admin_user, r_admin_user_remove, r_admin_users},
},
assets::{r_image, r_image_fallback_person},
error::{r_api_catch, r_catch},
@@ -28,7 +29,6 @@ use crate::{
player::r_player,
r_favicon, r_index,
style::{r_assets_css, r_assets_font, r_assets_js, r_assets_js_map},
- user::{r_user, r_user_remove},
},
};
use rocket::{
@@ -89,6 +89,8 @@ pub(super) fn build_rocket(state: Arc<State>) -> Rocket<Build> {
r_admin_log,
r_admin_new_user,
r_admin_users,
+ r_admin_user,
+ r_admin_user_remove,
r_api_root,
r_assets_css,
r_assets_font,
@@ -103,8 +105,6 @@ pub(super) fn build_rocket(state: Arc<State>) -> Rocket<Build> {
r_player,
r_playersync,
r_stream,
- r_user_remove,
- r_user,
r_version,
// Compat
// r_jellyfin_artists,
diff --git a/server/src/ui/admin/mod.rs b/server/src/ui/admin/mod.rs
index 79c9241..10037b5 100644
--- a/server/src/ui/admin/mod.rs
+++ b/server/src/ui/admin/mod.rs
@@ -6,25 +6,16 @@
pub mod import;
pub mod log;
+pub mod users;
use super::error::MyResult;
-use crate::{auth::hash_password, request_info::RequestInfo, ui_responder::UiResponse};
-use base64::{Engine, prelude::BASE64_URL_SAFE};
+use crate::{request_info::RequestInfo, ui_responder::UiResponse};
use jellycommon::{
- jellyobject::{OBB, ObjectBuffer, ObjectBufferBuilder},
- routes::u_admin_users,
+ jellyobject::{OBB, ObjectBuffer},
*,
};
-use jellydb::Query;
use jellyui::tr;
-use rand::random;
-use rocket::{
- FromForm,
- form::Form,
- get, post,
- response::{Flash, Redirect},
-};
-use std::str::FromStr;
+use rocket::get;
#[get("/admin/dashboard")]
pub async fn r_admin_dashboard(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
@@ -49,59 +40,3 @@ pub async fn r_admin_dashboard(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
);
Ok(ri.respond_ui(page))
}
-
-#[get("/admin/users")]
-pub fn r_admin_users(ri: RequestInfo) -> MyResult<UiResponse> {
- ri.require_admin()?;
-
- let mut users = Vec::new();
- ri.state.database.transaction(&mut |txn| {
- users.clear();
- let rows = txn
- .query(Query::from_str("FILTER Ulgn")?)?
- .collect::<Vec<_>>();
- for row in rows {
- let (row, _) = row?;
- users.push(txn.get(row)?.unwrap());
- }
- Ok(())
- })?;
-
- let mut list = ObjectBufferBuilder::default();
- for u in users {
- list.push(ADMIN_USER_LIST_ITEM, u.as_object());
- }
-
- let mut page = ObjectBufferBuilder::default();
- page.push(VIEW_TITLE, &*tr(ri.lang, "admin.users"));
- page.push(VIEW_ADMIN_USER_LIST, list.finish().as_object());
- Ok(ri.respond_ui(page))
-}
-
-#[derive(FromForm)]
-pub struct NewUser {
- login: String,
-}
-
-#[post("/admin/new_user", data = "<form>")]
-pub fn r_admin_new_user(ri: RequestInfo, form: Form<NewUser>) -> MyResult<Flash<Redirect>> {
- ri.require_admin()?;
-
- let password = BASE64_URL_SAFE.encode([(); 12].map(|()| random()));
- let password_hashed = hash_password(&form.login, &password);
-
- ri.state.database.transaction(&mut |txn| {
- let mut user = ObjectBufferBuilder::default();
- user.push(USER_LOGIN, &form.login);
- user.push(USER_PASSWORD, &password_hashed);
- user.push(USER_PASSWORD_REQUIRE_CHANGE, ());
- txn.insert(user.finish())?;
- Ok(())
- })?;
-
- Ok(Flash::new(
- Redirect::to(u_admin_users()),
- "success",
- format!("User created; password: {password}"),
- ))
-}
diff --git a/server/src/ui/admin/users.rs b/server/src/ui/admin/users.rs
new file mode 100644
index 0000000..654a6b9
--- /dev/null
+++ b/server/src/ui/admin/users.rs
@@ -0,0 +1,120 @@
+/*
+ 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) 2026 metamuffin <metamuffin.org>
+*/
+
+use std::str::FromStr;
+
+use base64::{Engine, prelude::BASE64_URL_SAFE};
+use jellycommon::{
+ jellyobject::{OBB, ObjectBufferBuilder, Path},
+ routes::u_admin_users,
+ *,
+};
+use jellydb::{Filter, Query, Sort};
+use jellyui::tr;
+use rand::random;
+use rocket::{
+ FromForm,
+ form::Form,
+ get, post,
+ response::{Flash, Redirect},
+};
+
+use crate::{
+ auth::hash_password, request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse,
+};
+
+#[get("/admin/users")]
+pub fn r_admin_users(ri: RequestInfo) -> MyResult<UiResponse> {
+ ri.require_admin()?;
+
+ let mut users = Vec::new();
+ ri.state.database.transaction(&mut |txn| {
+ users.clear();
+ let rows = txn
+ .query(Query::from_str("FILTER Ulgn")?)?
+ .collect::<Vec<_>>();
+ for row in rows {
+ let (row, _) = row?;
+ users.push(txn.get(row)?.unwrap());
+ }
+ Ok(())
+ })?;
+
+ let mut list = ObjectBufferBuilder::default();
+ for u in users {
+ list.push(ADMIN_USER_LIST_ITEM, u.as_object());
+ }
+
+ let mut page = ObjectBufferBuilder::default();
+ page.push(VIEW_TITLE, &*tr(ri.lang, "admin.users"));
+ page.push(VIEW_ADMIN_USER_LIST, list.finish().as_object());
+ Ok(ri.respond_ui(page))
+}
+
+#[derive(FromForm)]
+pub struct NewUser {
+ login: String,
+}
+
+#[post("/admin/new_user", data = "<form>")]
+pub fn r_admin_new_user(ri: RequestInfo, form: Form<NewUser>) -> MyResult<Flash<Redirect>> {
+ ri.require_admin()?;
+
+ let password = BASE64_URL_SAFE.encode([(); 12].map(|()| random()));
+ let password_hashed = hash_password(&form.login, &password);
+
+ ri.state.database.transaction(&mut |txn| {
+ let mut user = ObjectBufferBuilder::default();
+ user.push(USER_LOGIN, &form.login);
+ user.push(USER_PASSWORD, &password_hashed);
+ user.push(USER_PASSWORD_REQUIRE_CHANGE, ());
+ txn.insert(user.finish())?;
+ Ok(())
+ })?;
+
+ Ok(Flash::new(
+ Redirect::to(u_admin_users()),
+ "success",
+ format!("User created; password: {password}"),
+ ))
+}
+
+#[get("/admin/user/<name>")]
+pub fn r_admin_user(ri: RequestInfo<'_>, name: &str) -> MyResult<UiResponse> {
+ ri.require_admin()?;
+ let mut page = OBB::new();
+ ri.state.database.transaction(&mut |txn| {
+ if let Some(row) = txn.query_single(Query {
+ sort: Sort::None,
+ filter: Filter::Match(Path(vec![USER_LOGIN.0]), name.into()),
+ })? {
+ let user = txn.get(row)?.unwrap();
+ page = OBB::new();
+ page.push(VIEW_ADMIN_USER, user.as_object());
+ }
+ Ok(())
+ })?;
+
+ Ok(ri.respond_ui(page))
+}
+
+#[post("/admin/user/<name>/remove")]
+pub fn r_admin_user_remove(ri: RequestInfo<'_>, name: &str) -> MyResult<Flash<Redirect>> {
+ ri.require_admin()?;
+ ri.state.database.transaction(&mut |txn| {
+ if let Some(row) = txn.query_single(Query {
+ sort: Sort::None,
+ filter: Filter::Match(Path(vec![USER_LOGIN.0]), name.into()),
+ })? {
+ txn.remove(row)?;
+ }
+ Ok(())
+ })?;
+ Ok(Flash::success(
+ Redirect::to(u_admin_users()),
+ tr(ri.lang, "admin.users.remove_success"),
+ ))
+}
diff --git a/server/src/ui/mod.rs b/server/src/ui/mod.rs
index 28762f1..27535fa 100644
--- a/server/src/ui/mod.rs
+++ b/server/src/ui/mod.rs
@@ -16,9 +16,8 @@ pub mod assets;
pub mod error;
pub mod home;
pub mod node;
-pub mod style;
pub mod player;
-pub mod user;
+pub mod style;
#[get("/")]
pub async fn r_index(ri: RequestInfo<'_>) -> MyResult<Redirect> {
diff --git a/server/src/ui/user.rs b/server/src/ui/user.rs
deleted file mode 100644
index 31e521e..0000000
--- a/server/src/ui/user.rs
+++ /dev/null
@@ -1,28 +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) 2026 metamuffin <metamuffin.org>
-*/
-use crate::{request_info::RequestInfo, ui::error::MyResult};
-use jellycommon::routes::u_admin_users;
-use jellyui::tr;
-use rocket::{
- get, post,
- response::{Flash, Redirect, content::RawHtml},
-};
-
-#[get("/u/<name>")]
-pub fn r_user(ri: RequestInfo<'_>, name: &str) -> MyResult<RawHtml<String>> {
- ri.require_user()?;
- todo!()
-}
-
-#[post("/u/<name>/remove")]
-pub fn r_user_remove(ri: RequestInfo<'_>, name: &str) -> MyResult<Flash<Redirect>> {
- ri.require_admin()?;
- todo!();
- Ok(Flash::success(
- Redirect::to(u_admin_users()),
- tr(ri.lang, "admin.users.remove_success"),
- ))
-}