From b24f195e10e6361615468ecde84927456d922cb8 Mon Sep 17 00:00:00 2001 From: Trinity Pointard Date: Sat, 3 Oct 2020 13:21:31 +0200 Subject: [PATCH] refactor login first step toward ldap should have no functionnal change --- plume-models/src/users.rs | 46 ++++++++++++++++++++++++++++++++++----- src/api/mod.rs | 36 +++++++++++------------------- src/routes/session.rs | 25 +++------------------ 3 files changed, 57 insertions(+), 50 deletions(-) diff --git a/plume-models/src/users.rs b/plume-models/src/users.rs index 477f9758..eea12a58 100644 --- a/plume-models/src/users.rs +++ b/plume-models/src/users.rs @@ -292,11 +292,47 @@ impl User { bcrypt::hash(pass, 10).map_err(Error::from) } - pub fn auth(&self, pass: &str) -> bool { - self.hashed_password - .clone() - .map(|hashed| bcrypt::verify(pass, hashed.as_ref()).unwrap_or(false)) - .unwrap_or(false) + fn ldap_register() -> Result { + return Err(Error::NotFound); + unimplemented!() + } + + fn ldap_login(&self) -> bool { + return false; + } + + pub fn login(conn: &Connection, ident: &str, password: &str) -> Result { + let local_id = Instance::get_local()?.id; + let user = User::find_by_email(conn, ident) + .or_else(|_| User::find_by_name(conn, ident, local_id)) + .or_else(|_| User::ldap_register()) + .and_then(|u| if u.instance_id == local_id { + Ok(u) + } else { + Err(Error::NotFound) + }); + + match user { + Ok(user) if user.hashed_password.is_some() => { + if bcrypt::verify(password, user.hashed_password.as_ref().unwrap()).unwrap_or(false) { + Ok(user) + } else { + Err(Error::NotFound) + } + }, + Ok(user) => { + if user.ldap_login() { + Ok(user) + } else { + Err(Error::NotFound) + } + }, + e => { + let other = User::get(&*conn, 1).expect("No user is registered").hashed_password; + other.map(|pass| bcrypt::verify(password, &pass)); + e + }, + } } pub fn reset_password(&self, conn: &Connection, pass: &str) -> Result<()> { diff --git a/src/api/mod.rs b/src/api/mod.rs index 1ea9f6d3..bcac7509 100644 --- a/src/api/mod.rs +++ b/src/api/mod.rs @@ -62,30 +62,20 @@ pub fn oauth( let conn = &*rockets.conn; let app = App::find_by_client_id(conn, &query.client_id)?; if app.client_secret == query.client_secret { - if let Ok(user) = User::find_by_fqn(&rockets, &query.username) { - if user.auth(&query.password) { - let token = ApiToken::insert( - conn, - NewApiToken { - app_id: app.id, - user_id: user.id, - value: random_hex(), - scopes: query.scopes.clone(), - }, - )?; - Ok(Json(json!({ - "token": token.value - }))) - } else { - Ok(Json(json!({ - "error": "Invalid credentials" - }))) - } + if let Ok(user) = User::login(conn, &query.username, &query.password) { + let token = ApiToken::insert( + conn, + NewApiToken { + app_id: app.id, + user_id: user.id, + value: random_hex(), + scopes: query.scopes.clone(), + }, + )?; + Ok(Json(json!({ + "token": token.value + }))) } else { - // Making fake password verification to avoid different - // response times that would make it possible to know - // if a username is registered or not. - User::get(conn, 1)?.auth(&query.password); Ok(Json(json!({ "error": "Invalid credentials" }))) diff --git a/src/routes/session.rs b/src/routes/session.rs index 4d79f6f4..27902a46 100644 --- a/src/routes/session.rs +++ b/src/routes/session.rs @@ -48,38 +48,19 @@ pub fn create( rockets: PlumeRocket, ) -> RespondOrRedirect { let conn = &*rockets.conn; - let user = User::find_by_email(&*conn, &form.email_or_name) - .or_else(|_| User::find_by_fqn(&rockets, &form.email_or_name)); let mut errors = match form.validate() { Ok(_) => ValidationErrors::new(), Err(e) => e, }; - + let user = User::login(conn, &form.email_or_name, &form.password); let user_id = if let Ok(user) = user { - if !user.auth(&form.password) { - let mut err = ValidationError::new("invalid_login"); - err.message = Some(Cow::from("Invalid username, or password")); - errors.add("email_or_name", err); - String::new() - } else { - user.id.to_string() - } + user.id.to_string() } else { - // Fake password verification, only to avoid different login times - // that could be used to see if an email adress is registered or not - User::get(&*conn, 1) - .map(|u| u.auth(&form.password)) - .expect("No user is registered"); - let mut err = ValidationError::new("invalid_login"); err.message = Some(Cow::from("Invalid username, or password")); errors.add("email_or_name", err); - String::new() - }; - - if !errors.is_empty() { return render!(session::login(&rockets.to_context(), None, &*form, errors)).into(); - } + }; cookies.add_private( Cookie::build(AUTH_COOKIE, user_id)