aboutsummaryrefslogtreecommitdiff
path: root/server/src/routes/ui/account
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2024-01-20 00:50:20 +0100
committermetamuffin <metamuffin@disroot.org>2024-01-20 00:50:20 +0100
commit46c251655db7bb3d9aa814b1a5dde85336b0b9b1 (patch)
treeab0696f2c92e8854ce6aa0737877cc15184bd8b6 /server/src/routes/ui/account
parent1c37d32a0985ff7390313833345b9299f9f0b196 (diff)
downloadjellything-46c251655db7bb3d9aa814b1a5dde85336b0b9b1.tar
jellything-46c251655db7bb3d9aa814b1a5dde85336b0b9b1.tar.bz2
jellything-46c251655db7bb3d9aa814b1a5dde85336b0b9b1.tar.zst
replace sled with redb
Diffstat (limited to 'server/src/routes/ui/account')
-rw-r--r--server/src/routes/ui/account/mod.rs71
-rw-r--r--server/src/routes/ui/account/session/guard.rs18
-rw-r--r--server/src/routes/ui/account/settings.rs53
3 files changed, 88 insertions, 54 deletions
diff --git a/server/src/routes/ui/account/mod.rs b/server/src/routes/ui/account/mod.rs
index cd8695f..8af92a0 100644
--- a/server/src/routes/ui/account/mod.rs
+++ b/server/src/routes/ui/account/mod.rs
@@ -8,7 +8,7 @@ pub mod settings;
use super::{error::MyError, layout::LayoutPage};
use crate::{
- database::Database,
+ database::DataAcid,
routes::ui::{
account::session::Session, error::MyResult, home::rocket_uri_macro_r_home,
layout::DynLayoutPage,
@@ -18,7 +18,10 @@ use crate::{
use anyhow::anyhow;
use argon2::{password_hash::Salt, Argon2, PasswordHasher};
use chrono::Duration;
-use jellybase::CONF;
+use jellybase::{
+ database::{Ser, TableExt, T_INVITE, T_USER},
+ CONF,
+};
use jellycommon::user::{PermissionSet, Theme, User, UserPermission};
use rocket::{
form::{Contextual, Form},
@@ -121,7 +124,7 @@ pub fn r_account_logout() -> DynLayoutPage<'static> {
#[post("/account/register", data = "<form>")]
pub fn r_account_register_post<'a>(
- database: &'a State<Database>,
+ database: &'a State<DataAcid>,
_sess: Option<Session>,
form: Form<Contextual<'a, RegisterForm>>,
) -> MyResult<DynLayoutPage<'a>> {
@@ -131,15 +134,17 @@ pub fn r_account_register_post<'a>(
None => return Err(format_form_error(form)),
};
- if database.invite.remove(&form.invitation).unwrap().is_none() {
- return Err(MyError(anyhow!("invitation invalid")));
+ let txn = database.begin_write()?;
+ let mut invites = txn.open_table(T_INVITE)?;
+ let mut users = txn.open_table(T_USER)?;
+
+ if invites.remove(&*form.invitation)?.is_none() {
+ Err(anyhow!("invitation invalid"))?;
}
- match database
- .user
- .compare_and_swap(
- &form.username,
- None,
- Some(&User {
+ let prev_user = users
+ .insert(
+ &*form.username,
+ Ser(User {
display_name: form.username.clone(),
name: form.username.clone(),
password: hash_password(&form.username, &form.password),
@@ -147,27 +152,32 @@ pub fn r_account_register_post<'a>(
theme: Theme::Dark,
permissions: PermissionSet::default(),
}),
- )
- .unwrap()
- {
- Ok(_) => Ok(LayoutPage {
- title: "Registration successful".to_string(),
- content: markup::new! {
- h1 { @if logged_in {
- "Registration successful, you may switch account now."
- } else {
- "Registration successful, you may log in now."
- }}
- },
- ..Default::default()
- }),
- Err(_) => Err(MyError(anyhow!("username is taken"))),
+ )?
+ .map(|x| x.value().0);
+ if prev_user.is_some() {
+ Err(anyhow!("username taken"))?;
}
+
+ drop(users);
+ drop(invites);
+ txn.commit()?;
+
+ Ok(LayoutPage {
+ title: "Registration successful".to_string(),
+ content: markup::new! {
+ h1 { @if logged_in {
+ "Registration successful, you may switch account now."
+ } else {
+ "Registration successful, you may log in now."
+ }}
+ },
+ ..Default::default()
+ })
}
#[post("/account/login", data = "<form>")]
pub fn r_account_login_post(
- database: &State<Database>,
+ database: &State<DataAcid>,
jar: &CookieJar,
form: Form<Contextual<LoginForm>>,
) -> MyResult<Redirect> {
@@ -194,7 +204,7 @@ pub fn r_account_logout_post(jar: &CookieJar) -> MyResult<Redirect> {
}
pub fn login_logic(
- database: &Database,
+ database: &DataAcid,
username: &str,
password: &str,
expire: Option<i64>,
@@ -203,9 +213,8 @@ pub fn login_logic(
// hashing the password regardless if the accounts exists to prevent timing attacks
let password = hash_password(username, password);
- let mut user = database
- .user
- .get(&username.to_string())?
+ let mut user = T_USER
+ .get(database, username)?
.ok_or(anyhow!("invalid password"))?;
if user.password != password {
diff --git a/server/src/routes/ui/account/session/guard.rs b/server/src/routes/ui/account/session/guard.rs
index ae1ebd3..b2fd408 100644
--- a/server/src/routes/ui/account/session/guard.rs
+++ b/server/src/routes/ui/account/session/guard.rs
@@ -4,8 +4,9 @@
Copyright (C) 2023 metamuffin <metamuffin.org>
*/
use super::{AdminSession, Session};
-use crate::{database::Database, routes::ui::error::MyError};
+use crate::{database::DataAcid, routes::ui::error::MyError};
use anyhow::anyhow;
+use jellybase::database::{ReadableTable, T_USER};
use log::warn;
use rocket::{
async_trait,
@@ -35,8 +36,19 @@ impl Session {
username = "admin".to_string();
}
- let db = req.guard::<&State<Database>>().await.unwrap();
- let user = db.user.get(&username)?.ok_or(anyhow!("user not found"))?;
+ let db = req.guard::<&State<DataAcid>>().await.unwrap();
+
+ let user = {
+ let txn = db.inner.begin_read()?;
+ let table = txn.open_table(T_USER)?;
+ let user = table
+ .get(&*username)?
+ .ok_or(anyhow!("user not found"))?
+ .value()
+ .0;
+ drop(table);
+ user
+ };
Ok(Session { user })
}
diff --git a/server/src/routes/ui/account/settings.rs b/server/src/routes/ui/account/settings.rs
index f14478b..ecc0723 100644
--- a/server/src/routes/ui/account/settings.rs
+++ b/server/src/routes/ui/account/settings.rs
@@ -5,7 +5,7 @@
*/
use super::{format_form_error, hash_password};
use crate::{
- database::Database,
+ database::DataAcid,
routes::ui::{
account::{rocket_uri_macro_r_account_login, session::Session},
error::MyResult,
@@ -13,7 +13,11 @@ use crate::{
},
uri,
};
-use jellybase::permission::PermissionSetExt;
+use anyhow::anyhow;
+use jellybase::{
+ database::{ReadableTable, Ser, T_USER},
+ permission::PermissionSetExt,
+};
use jellycommon::user::{Theme, UserPermission};
use markup::{Render, RenderAttributeValue};
use rocket::{
@@ -97,7 +101,7 @@ pub fn r_account_settings(session: Session) -> DynLayoutPage<'static> {
#[post("/account/settings", data = "<form>")]
pub fn r_account_settings_post(
session: Session,
- database: &State<Database>,
+ database: &State<DataAcid>,
form: Form<Contextual<SettingsForm>>,
) -> MyResult<DynLayoutPage<'static>> {
session
@@ -111,23 +115,32 @@ pub fn r_account_settings_post(
};
let mut out = String::new();
- database.user.fetch_and_update(&session.user.name, |k| {
- k.map(|mut k| {
- if let Some(password) = &form.password {
- k.password = hash_password(&session.user.name, password);
- out += "Password updated\n";
- }
- if let Some(display_name) = &form.display_name {
- k.display_name = display_name.clone();
- out += "Display name updated\n";
- }
- if let Some(theme) = form.theme {
- k.theme = theme;
- out += "Theme updated\n";
- }
- k
- })
- })?;
+
+ let txn = database.begin_write()?;
+ let mut users = txn.open_table(T_USER)?;
+
+ let mut user = users
+ .get(&*session.user.name)?
+ .ok_or(anyhow!("user missing"))?
+ .value()
+ .0;
+
+ if let Some(password) = &form.password {
+ user.password = hash_password(&session.user.name, password);
+ out += "Password updated\n";
+ }
+ if let Some(display_name) = &form.display_name {
+ user.display_name = display_name.clone();
+ out += "Display name updated\n";
+ }
+ if let Some(theme) = form.theme {
+ user.theme = theme;
+ out += "Theme updated\n";
+ }
+
+ users.insert(&*session.user.name, Ser(user))?;
+ drop(users);
+ txn.commit()?;
Ok(settings_page(
session, // using the old session here, results in outdated theme being displayed