Reworked the database code to make use of the ? operator.

This commit is contained in:
Dennis Brentjes 2022-05-14 23:36:50 +02:00
parent 92e0257e74
commit cc26aed9a5
2 changed files with 71 additions and 88 deletions

View File

@ -123,14 +123,19 @@ impl<'r> FromRequest<'r> for schema::User {
let id = token.claims.uid; let id = token.claims.uid;
let conn = req.guard::<DbConn>().await.unwrap(); let conn = req.guard::<DbConn>().await.unwrap();
return Outcome::Success(schema::get_user(conn, id).await); return match schema::get_user(conn, id).await {
Ok(o) => Outcome::Success(o),
Err(_) => Outcome::Forward(())
}
} }
} }
#[get("/gamenights")] #[get("/gamenights")]
pub async fn gamenights(conn: DbConn, _user: schema::User) -> ApiResponseVariant { pub async fn gamenights(conn: DbConn, _user: schema::User) -> ApiResponseVariant {
let gamenights = schema::get_all_gamenights(conn).await; match schema::get_all_gamenights(conn).await {
ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(gamenights))) Ok(gamenights) => ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(gamenights))),
Err(error) => ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string())))
}
} }
#[get("/gamenights", rank = 2)] #[get("/gamenights", rank = 2)]

View File

@ -71,6 +71,18 @@ pub enum DatabaseError {
Query(String), Query(String),
} }
impl From<diesel::result::Error> for DatabaseError {
fn from(error: diesel::result::Error) -> Self {
Self::Query(error.to_string())
}
}
impl From<password_hash::Error> for DatabaseError {
fn from(error: password_hash::Error) -> Self {
Self::Hash(error)
}
}
impl std::fmt::Display for DatabaseError { impl std::fmt::Display for DatabaseError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> {
match self { match self {
@ -80,124 +92,90 @@ impl std::fmt::Display for DatabaseError {
} }
} }
pub async fn get_all_gamenights(conn: DbConn) -> Vec<GameNight> { pub async fn get_all_gamenights(conn: DbConn) -> Result<Vec<GameNight>, DatabaseError> {
conn.run(|c| gamenight::table.load::<GameNight>(c).unwrap()) Ok(conn.run(|c|
.await gamenight::table.load::<GameNight>(c)
).await?)
} }
pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> Result<(), DatabaseError> { pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> Result<usize, DatabaseError> {
let insert_result = conn.run(|c| { Ok(conn.run(|c|
diesel::insert_into(gamenight::table) diesel::insert_into(gamenight::table)
.values(new_gamenight) .values(new_gamenight)
.execute(c) .execute(c)
}) ).await?)
.await;
match insert_result {
Err(e) => Err(DatabaseError::Query(e.to_string())),
_ => Ok(()),
}
} }
pub async fn get_gamenight(conn: &DbConn, game_id: i32) -> Result<GameNight, DatabaseError> { pub async fn get_gamenight(conn: &DbConn, game_id: i32) -> Result<GameNight, DatabaseError> {
conn.run(move |c| { Ok(conn.run(move |c|
match gamenight::table.find(game_id).first(c) { gamenight::table.find(game_id).first(c)
Ok(gamenight) => Ok(gamenight), ).await?)
Err(error) => Err(DatabaseError::Query(error.to_string()))
}
}).await
} }
pub async fn delete_gamenight(conn: &DbConn, game_id: i32) -> Result<(), DatabaseError> { pub async fn delete_gamenight(conn: &DbConn, game_id: i32) -> Result<usize, DatabaseError> {
conn.run(move |c| { Ok(conn.run(move |c|
match diesel::delete(gamenight::table.filter(gamenight::id.eq(game_id))).execute(c) { diesel::delete(
Ok(_) => Ok(()), gamenight::table.filter(
Err(error) => Err(DatabaseError::Query(error.to_string())) gamenight::id.eq(game_id)
} )
}).await ).execute(c)
).await?)
} }
pub async fn insert_user(conn: DbConn, new_user: Register) -> Result<(), DatabaseError> { pub async fn insert_user(conn: DbConn, new_user: Register) -> Result<usize, DatabaseError> {
let salt = SaltString::generate(&mut OsRng); let salt = SaltString::generate(&mut OsRng);
let argon2 = Argon2::default(); let argon2 = Argon2::default();
let password_hash = match argon2.hash_password(new_user.password.as_bytes(), &salt) { let password_hash = argon2.hash_password(new_user.password.as_bytes(), &salt)?.to_string();
Ok(hash) => hash.to_string(),
Err(error) => return Err(DatabaseError::Hash(error)),
};
let user_insert_result = conn Ok(conn.run(move |c| {
.run(move |c| { c.transaction(|| {
c.transaction(|| { diesel::insert_into(user::table)
diesel::insert_into(user::table) .values((
.values(( user::username.eq(&new_user.username),
user::username.eq(&new_user.username), user::email.eq(&new_user.email),
user::email.eq(&new_user.email), user::role.eq(Role::User),
user::role.eq(Role::User), ))
)) .execute(c)?;
.execute(c)?;
let ids: Vec<i32> = match user::table let id: i32 = user::table
.filter( .filter(
user::username user::username
.eq(&new_user.username) .eq(&new_user.username)
.and(user::email.eq(&new_user.email)), .and(user::email.eq(&new_user.email)),
) )
.select(user::id) .select(user::id)
.get_results(c) .first(c)?;
{
Ok(id) => id,
Err(e) => return Err(e),
};
diesel::insert_into(pwd::table) diesel::insert_into(pwd::table)
.values((pwd::user_id.eq(ids[0]), pwd::password.eq(&password_hash))) .values((pwd::user_id.eq(id), pwd::password.eq(&password_hash)))
.execute(c) .execute(c)
})
}) })
.await; })
.await?)
match user_insert_result {
Err(e) => Err(DatabaseError::Query(e.to_string())),
_ => Ok(()),
}
} }
pub async fn login(conn: DbConn, login: Login) -> Result<LoginResult, DatabaseError> { pub async fn login(conn: DbConn, login: Login) -> Result<LoginResult, DatabaseError> {
conn.run(move |c| -> Result<LoginResult, DatabaseError> { conn.run(move |c| -> Result<LoginResult, DatabaseError> {
let id: i32 = match user::table let id: i32 = user::table
.filter(user::username.eq(&login.username)) .filter(user::username.eq(&login.username))
.or_filter(user::email.eq(&login.username)) .or_filter(user::email.eq(&login.username))
.select(user::id) .select(user::id)
.first(c) .first(c)?;
{
Ok(id) => id,
Err(error) => return Err(DatabaseError::Query(error.to_string())),
};
let pwd: String = match pwd::table let pwd: String = pwd::table
.filter(pwd::user_id.eq(id)) .filter(pwd::user_id.eq(id))
.select(pwd::password) .select(pwd::password)
.first(c) .first(c)?;
{
Ok(pwd) => pwd,
Err(error) => return Err(DatabaseError::Query(error.to_string())),
};
let parsed_hash = match PasswordHash::new(&pwd) { let parsed_hash = PasswordHash::new(&pwd)?;
Ok(hash) => hash,
Err(error) => return Err(DatabaseError::Hash(error)),
};
if Argon2::default() if Argon2::default()
.verify_password(&login.password.as_bytes(), &parsed_hash) .verify_password(&login.password.as_bytes(), &parsed_hash)
.is_ok() .is_ok()
{ {
let user: User = match user::table.find(id).first(c) { let user: User = user::table.find(id).first(c)?;
Ok(user) => user,
Err(error) => return Err(DatabaseError::Query(error.to_string()))
};
Ok(LoginResult { Ok(LoginResult {
result: true, result: true,
@ -213,9 +191,9 @@ pub async fn login(conn: DbConn, login: Login) -> Result<LoginResult, DatabaseEr
.await .await
} }
pub async fn get_user(conn: DbConn, id: i32) -> User { pub async fn get_user(conn: DbConn, id: i32) -> Result<User, DatabaseError> {
conn.run(move |c| user::table.filter(user::id.eq(id)).first(c).unwrap()) Ok(conn.run(move |c| user::table.filter(user::id.eq(id)).first(c))
.await .await?)
} }
pub fn unique_username( pub fn unique_username(