aboutsummaryrefslogtreecommitdiff
path: root/server/src/ui
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-02-25 13:25:41 +0100
committermetamuffin <metamuffin@disroot.org>2026-02-25 13:25:41 +0100
commit9c08495cca8b9aaf297c88da9ec98a619eb90762 (patch)
treefedb0ba09e45c51f7f1b9d5ce9ea5b9a47ce6f01 /server/src/ui
parent6949f8d40d1784d5a9c54dbe44e212fe2fae76f4 (diff)
downloadjellything-9c08495cca8b9aaf297c88da9ec98a619eb90762.tar
jellything-9c08495cca8b9aaf297c88da9ec98a619eb90762.tar.bz2
jellything-9c08495cca8b9aaf297c88da9ec98a619eb90762.tar.zst
user creation; flash message in request info
Diffstat (limited to 'server/src/ui')
-rw-r--r--server/src/ui/account/mod.rs12
-rw-r--r--server/src/ui/account/settings.rs19
-rw-r--r--server/src/ui/admin/import.rs6
-rw-r--r--server/src/ui/admin/mod.rs74
-rw-r--r--server/src/ui/home.rs2
-rw-r--r--server/src/ui/node.rs10
-rw-r--r--server/src/ui/player.rs10
7 files changed, 79 insertions, 54 deletions
diff --git a/server/src/ui/account/mod.rs b/server/src/ui/account/mod.rs
index 448f91e..1c44914 100644
--- a/server/src/ui/account/mod.rs
+++ b/server/src/ui/account/mod.rs
@@ -12,7 +12,11 @@ use crate::{
auth::login, request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse,
};
use anyhow::anyhow;
-use jellycommon::{VIEW_ACCOUNT_LOGIN, VIEW_ACCOUNT_LOGOUT, jellyobject::Object, routes::u_home};
+use jellycommon::{
+ VIEW_ACCOUNT_LOGIN, VIEW_ACCOUNT_LOGOUT,
+ jellyobject::OBB,
+ routes::{u_account_login, u_home},
+};
use rocket::{
FromForm,
form::{Contextual, Form},
@@ -25,12 +29,12 @@ use serde::{Deserialize, Serialize};
#[get("/account/login")]
pub async fn r_account_login(ri: RequestInfo<'_>) -> UiResponse {
- ri.respond_ui(Object::EMPTY.insert(VIEW_ACCOUNT_LOGIN, ()))
+ ri.respond_ui(OBB::new().with(VIEW_ACCOUNT_LOGIN, ()))
}
#[get("/account/logout")]
pub fn r_account_logout(ri: RequestInfo<'_>) -> UiResponse {
- ri.respond_ui(Object::EMPTY.insert(VIEW_ACCOUNT_LOGOUT, ()))
+ ri.respond_ui(OBB::new().with(VIEW_ACCOUNT_LOGOUT, ()))
}
#[derive(FromForm, Serialize, Deserialize)]
@@ -63,7 +67,7 @@ pub fn r_account_login_post(
pub fn r_account_logout_post(jar: &CookieJar) -> MyResult<Flash<Redirect>> {
jar.remove(Cookie::build("session"));
Ok(Flash::new(
- Redirect::found(u_home()),
+ Redirect::found(u_account_login()),
"success",
"Logged out!",
))
diff --git a/server/src/ui/account/settings.rs b/server/src/ui/account/settings.rs
index 2052c5e..bb4b323 100644
--- a/server/src/ui/account/settings.rs
+++ b/server/src/ui/account/settings.rs
@@ -9,7 +9,7 @@ use crate::{
};
use anyhow::anyhow;
use jellycommon::{
- jellyobject::{Object, ObjectBuffer, ObjectBufferBuilder, Path, Tag},
+ jellyobject::{OBB, Object, ObjectBuffer, Path, Tag},
routes::u_account_settings,
*,
};
@@ -19,7 +19,6 @@ use rocket::{
FromForm,
form::{self, Contextual, Form, validate::len},
get, post,
- request::FlashMessage,
response::{Flash, Redirect},
};
use std::ops::Range;
@@ -39,21 +38,9 @@ fn option_len<'v>(value: &Option<String>, range: Range<usize>) -> form::Result<'
}
#[get("/account/settings")]
-pub fn r_account_settings(ri: RequestInfo, flash: Option<FlashMessage>) -> MyResult<UiResponse> {
+pub fn r_account_settings(ri: RequestInfo) -> MyResult<UiResponse> {
let user = ri.require_user()?;
- let mut view = ObjectBufferBuilder::default();
- view.push(VIEW_USER_SETTINGS, user);
- if let Some(flash) = flash {
- view.push(
- VIEW_MESSAGE,
- ObjectBuffer::new(&mut [
- (MESSAGE_KIND.0, &flash.kind()),
- (MESSAGE_TEXT.0, &flash.message()),
- ])
- .as_object(),
- );
- }
- Ok(ri.respond_ui(view.finish()))
+ Ok(ri.respond_ui(OBB::new().with(VIEW_USER_SETTINGS, user)))
}
#[post("/account/settings", data = "<form>")]
diff --git a/server/src/ui/admin/import.rs b/server/src/ui/admin/import.rs
index b263705..eba2a3b 100644
--- a/server/src/ui/admin/import.rs
+++ b/server/src/ui/admin/import.rs
@@ -6,9 +6,9 @@
use crate::{request_info::RequestInfo, ui::error::MyResult, ui_responder::UiResponse};
use jellycommon::{
- ADMIN_IMPORT_BUSY, ADMIN_IMPORT_ERROR, VIEW_ADMIN_IMPORT,
- jellyobject::{Object, ObjectBuffer},
+ jellyobject::{OBB, ObjectBuffer},
routes::u_admin_import,
+ *,
};
use jellyimport::{
ImportConfig, import_wrap, is_importing,
@@ -41,7 +41,7 @@ pub async fn r_admin_import(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
.as_object()
.insert_multi(ADMIN_IMPORT_ERROR, &last_import_err);
- Ok(ri.respond_ui(Object::EMPTY.insert(VIEW_ADMIN_IMPORT, data.as_object())))
+ Ok(ri.respond_ui(OBB::new().with(VIEW_ADMIN_IMPORT, data.as_object())))
}
#[post("/admin/import?<incremental>")]
diff --git a/server/src/ui/admin/mod.rs b/server/src/ui/admin/mod.rs
index 3fa0591..79c9241 100644
--- a/server/src/ui/admin/mod.rs
+++ b/server/src/ui/admin/mod.rs
@@ -8,14 +8,22 @@ pub mod import;
pub mod log;
use super::error::MyResult;
-use crate::{request_info::RequestInfo, ui_responder::UiResponse};
+use crate::{auth::hash_password, request_info::RequestInfo, ui_responder::UiResponse};
+use base64::{Engine, prelude::BASE64_URL_SAFE};
use jellycommon::{
- jellyobject::{ObjectBuffer, ObjectBufferBuilder},
+ jellyobject::{OBB, ObjectBuffer, ObjectBufferBuilder},
+ routes::u_admin_users,
*,
};
use jellydb::Query;
use jellyui::tr;
-use rocket::get;
+use rand::random;
+use rocket::{
+ FromForm,
+ form::Form,
+ get, post,
+ response::{Flash, Redirect},
+};
use std::str::FromStr;
#[get("/admin/dashboard")]
@@ -28,17 +36,18 @@ pub async fn r_admin_dashboard(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
Ok(())
})?;
- Ok(ri.respond_ui(ObjectBuffer::new(&mut [
- (VIEW_TITLE.0, &&*tr(ri.lang, "admin.dashboard.title")),
- (VIEW_ADMIN_DASHBOARD.0, &()),
- (
- VIEW_ADMIN_INFO.0,
- &ObjectBuffer::new(&mut [
- (ADMIN_INFO_TITLE.0, &"Database Debug"),
- (ADMIN_INFO_TEXT.0, &db_debug.as_str()),
- ]),
- ),
- ])))
+ let mut page = OBB::new();
+ page.push(VIEW_TITLE, &*tr(ri.lang, "admin.dashboard.title"));
+ page.push(VIEW_ADMIN_DASHBOARD, ());
+ page.push(
+ VIEW_ADMIN_INFO,
+ ObjectBuffer::new(&mut [
+ (ADMIN_INFO_TITLE.0, &"Database Debug"),
+ (ADMIN_INFO_TEXT.0, &db_debug.as_str()),
+ ])
+ .as_object(),
+ );
+ Ok(ri.respond_ui(page))
}
#[get("/admin/users")]
@@ -62,8 +71,37 @@ pub fn r_admin_users(ri: RequestInfo) -> MyResult<UiResponse> {
for u in users {
list.push(ADMIN_USER_LIST_ITEM, u.as_object());
}
- Ok(ri.respond_ui(ObjectBuffer::new(&mut [(
- VIEW_ADMIN_USER_LIST.0,
- &list.finish().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/home.rs b/server/src/ui/home.rs
index 67e6e90..1a7da36 100644
--- a/server/src/ui/home.rs
+++ b/server/src/ui/home.rs
@@ -71,7 +71,7 @@ pub fn r_home(ri: RequestInfo<'_>) -> MyResult<UiResponse> {
.as_object(),
);
- Ok(ri.respond_ui(page.finish()))
+ Ok(ri.respond_ui(page))
}
fn home_row(ri: &RequestInfo<'_>, title: &str, query: &str) -> Result<ObjectBuffer> {
diff --git a/server/src/ui/node.rs b/server/src/ui/node.rs
index 14c90c1..509e9ae 100644
--- a/server/src/ui/node.rs
+++ b/server/src/ui/node.rs
@@ -8,7 +8,7 @@ use super::error::MyResult;
use crate::{request_info::RequestInfo, ui_responder::UiResponse};
use anyhow::Result;
use jellycommon::{
- jellyobject::{Object, ObjectBuffer, ObjectBufferBuilder, Path},
+ jellyobject::{OBB, Object, ObjectBuffer, ObjectBufferBuilder, Path},
*,
};
use jellydb::{Filter, MultiBehaviour, Query, Sort, SortOrder, Transaction, ValueSort};
@@ -19,7 +19,7 @@ use std::collections::BTreeMap;
pub fn r_node(ri: RequestInfo<'_>, slug: &str) -> MyResult<UiResponse> {
ri.require_user()?;
- let mut page_out = ObjectBuffer::empty();
+ let mut page = OBB::new();
ri.state.database.transaction(&mut |txn| {
if let Some(row) = txn.query_single(Query {
filter: Filter::Match(Path(vec![NO_SLUG.0]), slug.into()),
@@ -29,7 +29,7 @@ pub fn r_node(ri: RequestInfo<'_>, slug: &str) -> MyResult<UiResponse> {
let nku = Object::EMPTY.insert(NKU_NODE, n.as_object());
let nku = nku.as_object();
- let mut page = ObjectBufferBuilder::default();
+ page = OBB::new();
let title = nku
.get(NKU_NODE)
.unwrap_or_default()
@@ -41,13 +41,11 @@ pub fn r_node(ri: RequestInfo<'_>, slug: &str) -> MyResult<UiResponse> {
c_children(&mut page, txn, row, &nku)?;
c_credits(&mut page, txn, &nku)?;
c_credited(&mut page, txn, row)?;
-
- page_out = page.finish();
}
Ok(())
})?;
- Ok(ri.respond_ui(page_out))
+ Ok(ri.respond_ui(page))
}
fn c_children(
diff --git a/server/src/ui/player.rs b/server/src/ui/player.rs
index a03e455..4c592e4 100644
--- a/server/src/ui/player.rs
+++ b/server/src/ui/player.rs
@@ -6,7 +6,7 @@
use super::error::MyResult;
use crate::{request_info::RequestInfo, ui_responder::UiResponse};
use jellycommon::{
- jellyobject::{Object, ObjectBuffer, ObjectBufferBuilder, Path},
+ jellyobject::{OBB, Object, Path},
*,
};
use jellydb::{Filter, Query, Sort};
@@ -30,7 +30,7 @@ pub fn r_player(ri: RequestInfo<'_>, t: Option<f64>, slug: &str) -> MyResult<UiR
ri.require_user()?;
let _ = t;
- let mut page_out = ObjectBuffer::empty();
+ let mut page = OBB::new();
ri.state.database.transaction(&mut |txn| {
if let Some(row) = txn.query_single(Query {
filter: Filter::Match(Path(vec![NO_SLUG.0]), slug.into()),
@@ -39,7 +39,7 @@ pub fn r_player(ri: RequestInfo<'_>, t: Option<f64>, slug: &str) -> MyResult<UiR
let n = txn.get(row)?.unwrap();
let nku = Object::EMPTY.insert(NKU_NODE, n.as_object());
- let mut page = ObjectBufferBuilder::default();
+ page = OBB::new();
let title = nku
.as_object()
.get(NKU_NODE)
@@ -48,13 +48,11 @@ pub fn r_player(ri: RequestInfo<'_>, t: Option<f64>, slug: &str) -> MyResult<UiR
.unwrap_or_default();
page.push(VIEW_TITLE, title);
page.push(VIEW_PLAYER, nku.as_object());
-
- page_out = page.finish();
}
Ok(())
})?;
- Ok(ri.respond_ui(page_out))
+ Ok(ri.respond_ui(page))
}
// pub fn player_conf<'a>(item: Arc<Node>, playing: bool) -> anyhow::Result<DynRender<'a>> {