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 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")]
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)]

View File

@ -71,6 +71,18 @@ pub enum DatabaseError {
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 {
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<GameNight> {
conn.run(|c| gamenight::table.load::<GameNight>(c).unwrap())
.await
pub async fn get_all_gamenights(conn: DbConn) -> Result<Vec<GameNight>, DatabaseError> {
Ok(conn.run(|c|
gamenight::table.load::<GameNight>(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<usize, DatabaseError> {
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<GameNight, DatabaseError> {
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<usize, DatabaseError> {
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<usize, DatabaseError> {
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<i32> = 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<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))
.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<LoginResult, DatabaseEr
.await
}
pub async fn get_user(conn: DbConn, id: i32) -> 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<User, DatabaseError> {
Ok(conn.run(move |c| user::table.filter(user::id.eq(id)).first(c))
.await?)
}
pub fn unique_username(