aboutsummaryrefslogtreecommitdiff
path: root/logic
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2025-04-29 17:06:23 +0200
committermetamuffin <metamuffin@disroot.org>2025-04-29 17:06:23 +0200
commit212a0f23bc894faf88e159560c113f504349cc05 (patch)
treeee2ff0ff3b185d1874eb0e8fc4b75f1badf659b8 /logic
parentf73aa32549743b2967160d38c1622199c41524a4 (diff)
downloadjellything-212a0f23bc894faf88e159560c113f504349cc05.tar
jellything-212a0f23bc894faf88e159560c113f504349cc05.tar.bz2
jellything-212a0f23bc894faf88e159560c113f504349cc05.tar.zst
comiles again but still many logic holes
Diffstat (limited to 'logic')
-rw-r--r--logic/src/lib.rs1
-rw-r--r--logic/src/login.rs61
2 files changed, 62 insertions, 0 deletions
diff --git a/logic/src/lib.rs b/logic/src/lib.rs
index 1dba95d..54c9c40 100644
--- a/logic/src/lib.rs
+++ b/logic/src/lib.rs
@@ -13,3 +13,4 @@ pub mod session;
pub mod stats;
pub mod items;
pub mod admin;
+pub mod login;
diff --git a/logic/src/login.rs b/logic/src/login.rs
new file mode 100644
index 0000000..e9c2f93
--- /dev/null
+++ b/logic/src/login.rs
@@ -0,0 +1,61 @@
+/*
+ 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) 2025 metamuffin <metamuffin.org>
+*/
+use crate::session::create;
+use anyhow::{Result, anyhow};
+use argon2::{Argon2, PasswordHasher, password_hash::Salt};
+use jellybase::{CONF, database::Database};
+use jellycommon::user::UserPermission;
+use std::{collections::HashSet, time::Duration};
+
+pub fn login_logic(
+ database: &Database,
+ username: &str,
+ password: &str,
+ expire: Option<i64>,
+ drop_permissions: Option<HashSet<UserPermission>>,
+) -> Result<String> {
+ // hashing the password regardless if the accounts exists to better resist timing attacks
+ let password = hash_password(username, password);
+
+ let mut user = database
+ .get_user(username)?
+ .ok_or(anyhow!("invalid password"))?;
+
+ if user.password != password {
+ Err(anyhow!("invalid password"))?
+ }
+
+ if let Some(ep) = drop_permissions {
+ // remove all grant perms that are in `ep`
+ user.permissions
+ .0
+ .retain(|p, val| if *val { !ep.contains(p) } else { true })
+ }
+
+ Ok(create(
+ user.name,
+ user.permissions,
+ Duration::from_days(
+ CONF.login_expire
+ .min(expire.unwrap_or(i64::MAX))
+ .try_into()
+ .unwrap(),
+ ),
+ ))
+}
+
+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()
+}