diff options
Diffstat (limited to 'logic/src/login.rs')
-rw-r--r-- | logic/src/login.rs | 61 |
1 files changed, 61 insertions, 0 deletions
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() +} |