Skip to content

Commit

Permalink
For the session_auth_axum example, move the passhash into a separate (#…
Browse files Browse the repository at this point in the history
…2446)

non-serializable struct.

This prevents it from being returned in the
get_user() API, and prevents it from being unintentionally returned on any
new API the end-user may create on top of this example code.
  • Loading branch information
rcythr authored Mar 19, 2024
1 parent fda4dba commit 7ef186f
Showing 1 changed file with 46 additions and 23 deletions.
69 changes: 46 additions & 23 deletions examples/session_auth_axum/src/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,28 @@ use std::collections::HashSet;
pub struct User {
pub id: i64,
pub username: String,
pub password: String,
pub permissions: HashSet<String>,
}

// Explicitly is not Serialize/Deserialize!
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UserPasshash(String);

impl Default for User {
fn default() -> Self {
let permissions = HashSet::new();

Self {
id: -1,
username: "Guest".into(),
password: "".into(),
permissions,
}
}
}

#[cfg(feature = "ssr")]
pub mod ssr {
pub use super::User;
pub use super::{User, UserPasshash};
pub use axum_session_auth::{
Authentication, HasPermission, SessionSqlitePool,
};
Expand All @@ -42,7 +44,10 @@ pub mod ssr {
pub use bcrypt::{hash, verify, DEFAULT_COST};

impl User {
pub async fn get(id: i64, pool: &SqlitePool) -> Option<Self> {
pub async fn get_with_passhash(
id: i64,
pool: &SqlitePool,
) -> Option<(Self, UserPasshash)> {
let sqluser = sqlx::query_as::<_, SqlUser>(
"SELECT * FROM users WHERE id = ?",
)
Expand All @@ -63,10 +68,16 @@ pub mod ssr {
Some(sqluser.into_user(Some(sql_user_perms)))
}

pub async fn get_from_username(
pub async fn get(id: i64, pool: &SqlitePool) -> Option<Self> {
User::get_with_passhash(id, pool)
.await
.map(|(user, _)| user)
}

pub async fn get_from_username_with_passhash(
name: String,
pool: &SqlitePool,
) -> Option<Self> {
) -> Option<(Self, UserPasshash)> {
let sqluser = sqlx::query_as::<_, SqlUser>(
"SELECT * FROM users WHERE username = ?",
)
Expand All @@ -86,6 +97,15 @@ pub mod ssr {

Some(sqluser.into_user(Some(sql_user_perms)))
}

pub async fn get_from_username(
name: String,
pool: &SqlitePool,
) -> Option<Self> {
User::get_from_username_with_passhash(name, pool)
.await
.map(|(user, _)| user)
}
}

#[derive(sqlx::FromRow, Clone)]
Expand Down Expand Up @@ -137,20 +157,22 @@ pub mod ssr {
pub fn into_user(
self,
sql_user_perms: Option<Vec<SqlPermissionTokens>>,
) -> User {
User {
id: self.id,
username: self.username,
password: self.password,
permissions: if let Some(user_perms) = sql_user_perms {
user_perms
.into_iter()
.map(|x| x.token)
.collect::<HashSet<String>>()
} else {
HashSet::<String>::new()
) -> (User, UserPasshash) {
(
User {
id: self.id,
username: self.username,
permissions: if let Some(user_perms) = sql_user_perms {
user_perms
.into_iter()
.map(|x| x.token)
.collect::<HashSet<String>>()
} else {
HashSet::<String>::new()
},
},
}
UserPasshash(self.password),
)
}
}
}
Expand Down Expand Up @@ -180,11 +202,12 @@ pub async fn login(
let pool = pool()?;
let auth = auth()?;

let user: User = User::get_from_username(username, &pool)
.await
.ok_or_else(|| ServerFnError::new("User does not exist."))?;
let (user, UserPasshash(expected_passhash)) =
User::get_from_username_with_passhash(username, &pool)
.await
.ok_or_else(|| ServerFnError::new("User does not exist."))?;

match verify(password, &user.password)? {
match verify(password, &expected_passhash)? {
true => {
auth.login_user(user.id);
auth.remember_user(remember.is_some());
Expand Down

0 comments on commit 7ef186f

Please sign in to comment.