From cc26aed9a5683e5b202f0ab2eb2564d945f73db5 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Sat, 14 May 2022 23:36:50 +0200 Subject: [PATCH] Reworked the database code to make use of the ? operator. --- backend/src/api.rs | 11 +++- backend/src/schema.rs | 148 ++++++++++++++++++------------------------ 2 files changed, 71 insertions(+), 88 deletions(-) diff --git a/backend/src/api.rs b/backend/src/api.rs index cce2400..b560611 100644 --- a/backend/src/api.rs +++ b/backend/src/api.rs @@ -123,14 +123,19 @@ impl<'r> FromRequest<'r> for schema::User { let id = token.claims.uid; let conn = req.guard::().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")] pub async fn gamenights(conn: DbConn, _user: schema::User) -> ApiResponseVariant { - let gamenights = schema::get_all_gamenights(conn).await; - ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(gamenights))) + match schema::get_all_gamenights(conn).await { + Ok(gamenights) => ApiResponseVariant::Value(json!(ApiResponse::gamenight_response(gamenights))), + Err(error) => ApiResponseVariant::Value(json!(ApiResponse::error(error.to_string()))) + } } #[get("/gamenights", rank = 2)] diff --git a/backend/src/schema.rs b/backend/src/schema.rs index d1f8b06..a8ebe30 100644 --- a/backend/src/schema.rs +++ b/backend/src/schema.rs @@ -71,6 +71,18 @@ pub enum DatabaseError { Query(String), } +impl From for DatabaseError { + fn from(error: diesel::result::Error) -> Self { + Self::Query(error.to_string()) + } +} + +impl From for DatabaseError { + fn from(error: password_hash::Error) -> Self { + Self::Hash(error) + } +} + impl std::fmt::Display for DatabaseError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::result::Result<(), std::fmt::Error> { match self { @@ -80,124 +92,90 @@ impl std::fmt::Display for DatabaseError { } } -pub async fn get_all_gamenights(conn: DbConn) -> Vec { - conn.run(|c| gamenight::table.load::(c).unwrap()) - .await +pub async fn get_all_gamenights(conn: DbConn) -> Result, DatabaseError> { + Ok(conn.run(|c| + gamenight::table.load::(c) + ).await?) } -pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> Result<(), DatabaseError> { - let insert_result = conn.run(|c| { +pub async fn insert_gamenight(conn: DbConn, new_gamenight: GameNightNoId) -> Result { + Ok(conn.run(|c| diesel::insert_into(gamenight::table) .values(new_gamenight) .execute(c) - }) - .await; - - match insert_result { - Err(e) => Err(DatabaseError::Query(e.to_string())), - _ => Ok(()), - } + ).await?) } pub async fn get_gamenight(conn: &DbConn, game_id: i32) -> Result { - conn.run(move |c| { - match gamenight::table.find(game_id).first(c) { - Ok(gamenight) => Ok(gamenight), - Err(error) => Err(DatabaseError::Query(error.to_string())) - } - }).await + Ok(conn.run(move |c| + gamenight::table.find(game_id).first(c) + ).await?) } -pub async fn delete_gamenight(conn: &DbConn, game_id: i32) -> Result<(), DatabaseError> { - conn.run(move |c| { - match diesel::delete(gamenight::table.filter(gamenight::id.eq(game_id))).execute(c) { - Ok(_) => Ok(()), - Err(error) => Err(DatabaseError::Query(error.to_string())) - } - }).await +pub async fn delete_gamenight(conn: &DbConn, game_id: i32) -> Result { + Ok(conn.run(move |c| + diesel::delete( + gamenight::table.filter( + gamenight::id.eq(game_id) + ) + ).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 { let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); - let password_hash = match argon2.hash_password(new_user.password.as_bytes(), &salt) { - Ok(hash) => hash.to_string(), - Err(error) => return Err(DatabaseError::Hash(error)), - }; + let password_hash = argon2.hash_password(new_user.password.as_bytes(), &salt)?.to_string(); - let user_insert_result = conn - .run(move |c| { - c.transaction(|| { - diesel::insert_into(user::table) - .values(( - user::username.eq(&new_user.username), - user::email.eq(&new_user.email), - user::role.eq(Role::User), - )) - .execute(c)?; + Ok(conn.run(move |c| { + c.transaction(|| { + diesel::insert_into(user::table) + .values(( + user::username.eq(&new_user.username), + user::email.eq(&new_user.email), + user::role.eq(Role::User), + )) + .execute(c)?; - let ids: Vec = match user::table - .filter( - user::username - .eq(&new_user.username) - .and(user::email.eq(&new_user.email)), - ) - .select(user::id) - .get_results(c) - { - Ok(id) => id, - Err(e) => return Err(e), - }; + let id: i32 = user::table + .filter( + user::username + .eq(&new_user.username) + .and(user::email.eq(&new_user.email)), + ) + .select(user::id) + .first(c)?; - diesel::insert_into(pwd::table) - .values((pwd::user_id.eq(ids[0]), pwd::password.eq(&password_hash))) - .execute(c) - }) + diesel::insert_into(pwd::table) + .values((pwd::user_id.eq(id), pwd::password.eq(&password_hash))) + .execute(c) }) - .await; - - match user_insert_result { - Err(e) => Err(DatabaseError::Query(e.to_string())), - _ => Ok(()), - } + }) + .await?) } pub async fn login(conn: DbConn, login: Login) -> Result { conn.run(move |c| -> Result { - let id: i32 = match user::table + let id: i32 = user::table .filter(user::username.eq(&login.username)) .or_filter(user::email.eq(&login.username)) .select(user::id) - .first(c) - { - Ok(id) => id, - Err(error) => return Err(DatabaseError::Query(error.to_string())), - }; + .first(c)?; - let pwd: String = match pwd::table + let pwd: String = pwd::table .filter(pwd::user_id.eq(id)) .select(pwd::password) - .first(c) - { - Ok(pwd) => pwd, - Err(error) => return Err(DatabaseError::Query(error.to_string())), - }; + .first(c)?; - let parsed_hash = match PasswordHash::new(&pwd) { - Ok(hash) => hash, - Err(error) => return Err(DatabaseError::Hash(error)), - }; + let parsed_hash = PasswordHash::new(&pwd)?; if Argon2::default() .verify_password(&login.password.as_bytes(), &parsed_hash) .is_ok() { - let user: User = match user::table.find(id).first(c) { - Ok(user) => user, - Err(error) => return Err(DatabaseError::Query(error.to_string())) - }; + let user: User = user::table.find(id).first(c)?; Ok(LoginResult { result: true, @@ -213,9 +191,9 @@ pub async fn login(conn: DbConn, login: Login) -> Result User { - conn.run(move |c| user::table.filter(user::id.eq(id)).first(c).unwrap()) - .await +pub async fn get_user(conn: DbConn, id: i32) -> Result { + Ok(conn.run(move |c| user::table.filter(user::id.eq(id)).first(c)) + .await?) } pub fn unique_username(