aboutsummaryrefslogtreecommitdiff
path: root/server/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2026-01-25 15:01:38 +0100
committermetamuffin <metamuffin@disroot.org>2026-01-25 15:01:38 +0100
commit5075aede44cb8ab2df10e6debba38483e8d11e96 (patch)
treef719e4b4a0c29f3a27b4fa7cf0a6ee6f7739125c /server/src
parent53361f4c6027d1569a707ce58889bc2c2ea3749c (diff)
downloadjellything-5075aede44cb8ab2df10e6debba38483e8d11e96.tar
jellything-5075aede44cb8ab2df10e6debba38483e8d11e96.tar.bz2
jellything-5075aede44cb8ab2df10e6debba38483e8d11e96.tar.zst
remove some unused imports; css reload; port login logic
Diffstat (limited to 'server/src')
-rw-r--r--server/src/api.rs14
-rw-r--r--server/src/auth.rs63
-rw-r--r--server/src/routes.rs3
-rw-r--r--server/src/ui/account/mod.rs15
-rw-r--r--server/src/ui/admin/import.rs10
-rw-r--r--server/src/ui/admin/log.rs13
-rw-r--r--server/src/ui/admin/mod.rs2
-rw-r--r--server/src/ui/admin/user.rs15
-rw-r--r--server/src/ui/assets.rs3
-rw-r--r--server/src/ui/error.rs2
-rw-r--r--server/src/ui/home.rs3
-rw-r--r--server/src/ui/items.rs6
-rw-r--r--server/src/ui/mod.rs12
-rw-r--r--server/src/ui/node.rs12
-rw-r--r--server/src/ui/player.rs19
-rw-r--r--server/src/ui/search.rs5
-rw-r--r--server/src/ui/stats.rs5
-rw-r--r--server/src/ui/style.rs47
18 files changed, 87 insertions, 162 deletions
diff --git a/server/src/api.rs b/server/src/api.rs
index 45bcd90..2b3d016 100644
--- a/server/src/api.rs
+++ b/server/src/api.rs
@@ -4,8 +4,7 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::ui::error::MyResult;
-use rocket::{get, post, response::Redirect, serde::json::Json};
-use serde_json::{Value, json};
+use rocket::{get, response::Redirect, serde::json::Json};
#[get("/api")]
pub fn r_api_root() -> Redirect {
@@ -38,17 +37,6 @@ pub fn r_version() -> &'static str {
// }
// }
-#[post("/api/create_session", data = "<data>")]
-pub fn r_api_account_login(data: Json<CreateSessionParams>) -> MyResult<Value> {
- let token = login_logic(
- &data.username,
- &data.password,
- data.expire,
- data.drop_permissions.clone(),
- )?;
- Ok(json!(token))
-}
-
#[get("/nodes_modified?<since>")]
pub fn r_nodes_modified_since(session: A<Session>, since: u64) -> MyResult<Json<Vec<NodeID>>> {
let nodes = get_nodes_modified_since(&session.0, since)?;
diff --git a/server/src/auth.rs b/server/src/auth.rs
index e84c4d1..0e523ed 100644
--- a/server/src/auth.rs
+++ b/server/src/auth.rs
@@ -5,8 +5,13 @@
*/
use crate::State;
-use anyhow::{Result, anyhow};
-use jellycommon::jellyobject::ObjectBuffer;
+use anyhow::{Result, anyhow, bail};
+use argon2::{Argon2, PasswordHasher, password_hash::Salt};
+use jellycommon::{
+ USER_LOGIN, USER_PASSWORD,
+ jellyobject::{ObjectBuffer, Path},
+};
+use jellydb::query::{Filter, Query, Sort};
pub fn token_to_user(state: &State, token: &str) -> Result<ObjectBuffer> {
let user_row = token::validate(&state.session_key, token)?;
@@ -20,6 +25,55 @@ pub fn token_to_user(state: &State, token: &str) -> Result<ObjectBuffer> {
user.ok_or(anyhow!("user was deleted"))
}
+pub fn login(state: &State, username: &str, password: &str, expire: Option<i64>) -> Result<String> {
+ let password = hash_password(username, password);
+
+ let mut user_row = None;
+ let mut user = None;
+ state.database.read_transaction(&mut |txn| {
+ user_row = state.users.query_single(
+ txn,
+ Query {
+ filter: Filter::Match(Path(vec![USER_LOGIN.0]), username.as_bytes().to_vec()),
+ sort: Sort::None,
+ },
+ )?;
+ if let Some(ur) = user_row {
+ user = state.users.get(txn, ur)?;
+ }
+ Ok(())
+ });
+
+ let (Some(user_row), Some(user)) = (user_row, user) else {
+ bail!("unknown user");
+ };
+ let Some(correct_pw) = user.as_object().get(USER_PASSWORD) else {
+ bail!("password login is disabled")
+ };
+ if password != correct_pw {
+ bail!("incorrect password")
+ }
+
+ Ok(token::create(
+ &state.session_key,
+ user_row,
+ expire.unwrap_or(60 * 60 * 24 * 30),
+ ))
+}
+
+pub fn hash_password(username: &str, password: &str) -> Vec<u8> {
+ Argon2::default()
+ .hash_password(
+ format!("{username}\0{password}").as_bytes(),
+ <&str as TryInto<Salt>>::try_into("IYMa13osbNeLJKnQ1T8LlA").unwrap(),
+ )
+ .unwrap()
+ .hash
+ .unwrap()
+ .as_bytes()
+ .to_vec()
+}
+
pub mod token {
use aes_gcm_siv::{
Aes256GcmSiv, KeyInit,
@@ -32,7 +86,6 @@ pub mod token {
};
use chrono::Utc;
use jellydb::table::RowNum;
- use std::time::Duration;
pub struct SessionKey(Aes256GcmSiv);
@@ -43,8 +96,8 @@ pub mod token {
}
}
- pub fn create(sk: &SessionKey, user: RowNum, expire: Duration) -> String {
- let expire_ts = Utc::now().timestamp() + expire.as_secs() as i64;
+ pub fn create(sk: &SessionKey, user: RowNum, expire: i64) -> String {
+ let expire_ts = Utc::now().timestamp() + expire;
let mut plain = Vec::new();
plain.extend(user.to_be_bytes());
plain.extend(expire_ts.to_be_bytes());
diff --git a/server/src/routes.rs b/server/src/routes.rs
index 62a70b7..19c76b2 100644
--- a/server/src/routes.rs
+++ b/server/src/routes.rs
@@ -5,7 +5,7 @@
*/
use crate::{
State,
- api::{r_api_account_login, r_api_root, r_nodes_modified_since, r_version},
+ api::{r_api_root, r_nodes_modified_since, r_version},
compat::youtube::{r_youtube_channel, r_youtube_embed, r_youtube_watch},
logic::{
playersync::{PlayersyncChannels, r_playersync},
@@ -127,7 +127,6 @@ pub fn build_rocket(state: Arc<State>) -> Rocket<Build> {
r_stats,
r_stream,
// API
- r_api_account_login,
r_nodes_modified_since,
r_api_root,
r_version,
diff --git a/server/src/ui/account/mod.rs b/server/src/ui/account/mod.rs
index 35cf52e..429b70a 100644
--- a/server/src/ui/account/mod.rs
+++ b/server/src/ui/account/mod.rs
@@ -6,25 +6,16 @@
pub mod settings;
use super::error::MyError;
-use crate::{
- request_info::{language::AcceptLanguage, A},
- ui::{error::MyResult, home::rocket_uri_macro_r_home},
-};
+use crate::ui::{error::MyResult, home::rocket_uri_macro_r_home};
use anyhow::anyhow;
use jellyimport::is_importing;
-use jellylogic::{account::register_user, login::login_logic, session::Session};
-use jellyui::{
- account::{AccountLogin, AccountLogout, AccountRegister, AccountRegisterSuccess},
- render_page,
- scaffold::{RenderInfo, SessionInfo},
-};
use rocket::{
+ FromForm,
form::{Contextual, Form},
get,
http::{Cookie, CookieJar},
post,
- response::{content::RawHtml, Redirect},
- FromForm,
+ response::{Redirect, content::RawHtml},
};
use serde::{Deserialize, Serialize};
diff --git a/server/src/ui/admin/import.rs b/server/src/ui/admin/import.rs
index fb33c67..79b8374 100644
--- a/server/src/ui/admin/import.rs
+++ b/server/src/ui/admin/import.rs
@@ -4,25 +4,19 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use std::time::Duration;
-
-use crate::{
- request_info::{A, RequestInfo},
- ui::error::MyResult,
-};
+use crate::{request_info::RequestInfo, ui::error::MyResult};
use jellycommon::routes::u_admin_import;
use jellyimport::{
is_importing,
reporting::{IMPORT_ERRORS, IMPORT_PROGRESS},
};
-use jellylogic::{admin::do_import, session::Session};
-use jellyui::{admin::import::AdminImportPage, locale::tr, render_page};
use rocket::{
get, post,
request::FlashMessage,
response::{Flash, Redirect, content::RawHtml},
};
use rocket_ws::{Message, Stream, WebSocket};
+use std::time::Duration;
use tokio::time::sleep;
#[get("/admin/import", rank = 2)]
diff --git a/server/src/ui/admin/log.rs b/server/src/ui/admin/log.rs
index e948daa..da70360 100644
--- a/server/src/ui/admin/log.rs
+++ b/server/src/ui/admin/log.rs
@@ -3,18 +3,7 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::{
- request_info::{A, RequestInfo},
- ui::error::MyResult,
-};
-use jellylogic::{
- admin::log::{get_log_buffer, get_log_stream},
- session::Session,
-};
-use jellyui::{
- admin::log::{ServerLogPage, render_log_line},
- render_page,
-};
+use crate::{request_info::RequestInfo, ui::error::MyResult};
use rocket::{get, response::content::RawHtml};
use rocket_ws::{Message, Stream, WebSocket};
use serde_json::json;
diff --git a/server/src/ui/admin/mod.rs b/server/src/ui/admin/mod.rs
index 9759627..5ee05b7 100644
--- a/server/src/ui/admin/mod.rs
+++ b/server/src/ui/admin/mod.rs
@@ -11,8 +11,6 @@ use super::error::MyResult;
use crate::request_info::RequestInfo;
use jellycommon::routes::u_admin_dashboard;
use jellyimport::is_importing;
-use jellylogic::admin::{create_invite, delete_invite, list_invites, update_search_index};
-use jellyui::{admin::AdminDashboardPage, locale::tr, render_page};
use rocket::{
FromForm,
form::Form,
diff --git a/server/src/ui/admin/user.rs b/server/src/ui/admin/user.rs
index 03950df..b4770c8 100644
--- a/server/src/ui/admin/user.rs
+++ b/server/src/ui/admin/user.rs
@@ -5,21 +5,12 @@
*/
use crate::{request_info::RequestInfo, ui::error::MyResult};
use anyhow::Context;
-use jellycommon::{
- routes::{u_admin_user, u_admin_users},
- user::UserPermission,
-};
-use jellylogic::admin::user::{admin_users, delete_user, get_user, update_user_perms, GrantState};
-use jellyui::{
- admin::user::{AdminUserPage, AdminUsersPage},
- locale::tr,
- render_page,
-};
+use jellycommon::routes::{u_admin_user, u_admin_users};
use rocket::{
+ FromForm, FromFormField,
form::Form,
get, post,
- response::{content::RawHtml, Flash, Redirect},
- FromForm, FromFormField,
+ response::{Flash, Redirect, content::RawHtml},
};
#[get("/admin/users")]
diff --git a/server/src/ui/assets.rs b/server/src/ui/assets.rs
index 6dc6731..8f3fb4a 100644
--- a/server/src/ui/assets.rs
+++ b/server/src/ui/assets.rs
@@ -4,10 +4,7 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::error::MyResult;
-use crate::request_info::{A, cache::CacheControlImage};
use anyhow::{Context, anyhow};
-use jellycommon::{Asset, NodeID, PictureSlot, api::NodeFilterSort};
-use jellylogic::{assets::get_node_thumbnail, node::get_node, session::Session};
use rocket::{get, http::ContentType, response::Redirect};
use std::str::FromStr;
diff --git a/server/src/ui/error.rs b/server/src/ui/error.rs
index d94639a..0f279fc 100644
--- a/server/src/ui/error.rs
+++ b/server/src/ui/error.rs
@@ -3,8 +3,6 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::CONF;
-use jellyui::{error::ErrorPage, locale::Language, render_page, scaffold::RenderInfo};
use log::info;
use rocket::{
catch,
diff --git a/server/src/ui/home.rs b/server/src/ui/home.rs
index 499c3cd..4e9fd28 100644
--- a/server/src/ui/home.rs
+++ b/server/src/ui/home.rs
@@ -5,9 +5,6 @@
*/
use super::error::MyResult;
-use crate::request_info::{accept::Accept, RequestInfo};
-use jellycommon::api::ApiHomeResponse;
-use jellyui::{home::HomePage, render_page};
use rocket::{get, response::content::RawHtml, serde::json::Json, Either};
#[get("/home")]
diff --git a/server/src/ui/items.rs b/server/src/ui/items.rs
index 86aaf12..cc8c18f 100644
--- a/server/src/ui/items.rs
+++ b/server/src/ui/items.rs
@@ -4,11 +4,7 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::error::MyError;
-use crate::request_info::{accept::Accept, filter_sort::ANodeFilterSort, RequestInfo};
-use jellycommon::api::ApiItemsResponse;
-use jellylogic::items::all_items;
-use jellyui::{items::ItemsPage, render_page};
-use rocket::{get, response::content::RawHtml, serde::json::Json, Either};
+use rocket::{Either, get, response::content::RawHtml, serde::json::Json};
#[get("/items?<page>&<filter..>")]
pub fn r_items(
diff --git a/server/src/ui/mod.rs b/server/src/ui/mod.rs
index 946401e..92b93fe 100644
--- a/server/src/ui/mod.rs
+++ b/server/src/ui/mod.rs
@@ -3,23 +3,17 @@
which is licensed under the GNU Affero General Public License (version 3); see /COPYING.
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
-use crate::{
- request_info::{language::AcceptLanguage, A},
- CONF,
-};
use error::MyResult;
use home::rocket_uri_macro_r_home;
-use jellylogic::session::Session;
-use jellyui::{render_page, scaffold::RenderInfo, CustomPage};
use rocket::{
+ Either,
futures::FutureExt,
get,
- response::{content::RawHtml, Redirect},
- Either,
+ response::{Redirect, content::RawHtml},
};
use std::{future::Future, pin::Pin};
use tokio::{
- fs::{read_to_string, File},
+ fs::{File, read_to_string},
io::AsyncRead,
};
diff --git a/server/src/ui/node.rs b/server/src/ui/node.rs
index fac1909..85beac6 100644
--- a/server/src/ui/node.rs
+++ b/server/src/ui/node.rs
@@ -4,18 +4,12 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::error::MyResult;
-use crate::request_info::{filter_sort::ANodeFilterSort, RequestInfo, A};
-use jellycommon::{
- api::{ApiNodeResponse, NodeFilterSort},
- NodeID,
-};
-use jellylogic::node::get_node;
-use jellyui::{node_page::NodePage, render_page};
-use rocket::{get, response::content::RawHtml, serde::json::Json, Either};
+use crate::request_info::RequestInfo;
+use rocket::{Either, get, response::content::RawHtml, serde::json::Json};
#[get("/n/<id>?<parents>&<children>&<filter..>")]
pub async fn r_node(
- ri: RequestInfo,
+ ri: RequestInfo<'_>,
id: A<NodeID>,
filter: Option<ANodeFilterSort>,
parents: bool,
diff --git a/server/src/ui/player.rs b/server/src/ui/player.rs
index d43f3ea..b9d7d2e 100644
--- a/server/src/ui/player.rs
+++ b/server/src/ui/player.rs
@@ -4,22 +4,11 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
*/
use super::error::MyResult;
-use crate::{
- request_info::{RequestInfo, A},
- CONF,
-};
-use jellycommon::{
- api::NodeFilterSort,
- stream::{StreamContainer, StreamSpec},
- user::{PermissionSet, PlayerKind},
- NodeID,
-};
-use jellylogic::node::get_node;
-use jellyui::{node_page::NodePage, render_page};
+use crate::request_info::RequestInfo;
+use jellycommon::stream::{StreamContainer, StreamSpec};
use rocket::{
- get,
- response::{content::RawHtml, Redirect},
- Either,
+ Either, get,
+ response::{Redirect, content::RawHtml},
};
use std::time::Duration;
diff --git a/server/src/ui/search.rs b/server/src/ui/search.rs
index 8a67672..fce79e3 100644
--- a/server/src/ui/search.rs
+++ b/server/src/ui/search.rs
@@ -6,10 +6,7 @@
use super::error::MyResult;
use crate::request_info::RequestInfo;
use anyhow::anyhow;
-use jellycommon::api::ApiSearchResponse;
-use jellylogic::search::search;
-use jellyui::{render_page, search::SearchPage};
-use rocket::{get, response::content::RawHtml, serde::json::Json, Either};
+use rocket::{Either, get, response::content::RawHtml, serde::json::Json};
#[get("/search?<query>&<page>")]
pub async fn r_search(
diff --git a/server/src/ui/stats.rs b/server/src/ui/stats.rs
index b0225e6..fc4ae64 100644
--- a/server/src/ui/stats.rs
+++ b/server/src/ui/stats.rs
@@ -5,10 +5,7 @@
*/
use super::error::MyError;
use crate::request_info::RequestInfo;
-use jellycommon::api::ApiStatsResponse;
-use jellylogic::stats::stats;
-use jellyui::{render_page, stats::StatsPage};
-use rocket::{get, response::content::RawHtml, serde::json::Json, Either};
+use rocket::{Either, get, response::content::RawHtml, serde::json::Json};
#[get("/stats")]
pub fn r_stats(
diff --git a/server/src/ui/style.rs b/server/src/ui/style.rs
index 5226b6a..2b7d2de 100644
--- a/server/src/ui/style.rs
+++ b/server/src/ui/style.rs
@@ -4,50 +4,13 @@
Copyright (C) 2026 metamuffin <metamuffin.org>
Copyright (C) 2023 tpart
*/
+use jellyui::{css_bundle, js_bundle, js_bundle_map};
use rocket::{
get,
http::{ContentType, Header},
response::Responder,
};
-
-macro_rules! concat_files {
- ([$base: expr], $($files:literal),*) => {{
- #[cfg(any(debug_assertions, feature = "hot-css"))]
- {
- use std::{fs::read_to_string, path::PathBuf, str::FromStr};
- [ $($files),* ]
- .into_iter()
- .map(|n| {
- read_to_string({
- let p = PathBuf::from_str(file!()).unwrap().parent().unwrap().join($base).join(n);
- log::info!("load {p:?}");
- p
- })
- .unwrap()
- })
- .collect::<Vec<_>>()
- .join("\n")
- }
- #[cfg(not(any(debug_assertions, feature = "hot-css")))]
- concat!($(include_str!(concat!($base, "/", $files))),*).to_string()
- }};
-}
-
-fn css_bundle() -> String {
- concat_files!(
- ["../../../web/style"],
- "layout.css",
- "player.css",
- "nodepage.css",
- "nodecard.css",
- "js-player.css",
- "js-transition.css",
- "forms.css",
- "props.css",
- "themes.css",
- "navbar.css"
- )
-}
+use std::borrow::Cow;
pub struct CachedAsset<T>(pub T);
impl<'r, 'o: 'r, T: Responder<'r, 'o>> Responder<'r, 'o> for CachedAsset<T> {
@@ -61,7 +24,7 @@ impl<'r, 'o: 'r, T: Responder<'r, 'o>> Responder<'r, 'o> for CachedAsset<T> {
}
#[get("/assets/style.css")]
-pub fn r_assets_style() -> CachedAsset<(ContentType, String)> {
+pub fn r_assets_style() -> CachedAsset<(ContentType, Cow<'static, str>)> {
CachedAsset((ContentType::CSS, css_bundle()))
}
@@ -74,10 +37,10 @@ pub fn r_assets_font() -> CachedAsset<(ContentType, &'static [u8])> {
}
#[get("/assets/bundle.js")]
-pub fn r_assets_js() -> CachedAsset<(ContentType, String)> {
+pub fn r_assets_js() -> CachedAsset<(ContentType, Cow<'static, str>)> {
CachedAsset((ContentType::JavaScript, js_bundle()))
}
#[get("/assets/bundle.js.map")]
-pub fn r_assets_js_map() -> CachedAsset<(ContentType, String)> {
+pub fn r_assets_js_map() -> CachedAsset<(ContentType, Cow<'static, str>)> {
CachedAsset((ContentType::JSON, js_bundle_map()))
}