diff --git a/identity-api-rs/src/database/actions.rs b/identity-api-rs/src/database/actions.rs index 88de978..db5c1e9 100644 --- a/identity-api-rs/src/database/actions.rs +++ b/identity-api-rs/src/database/actions.rs @@ -95,10 +95,7 @@ macro_rules! retrieve_sub_entry { }}; } -pub fn entry_recursive( - entry_id: &str, - conn: Connection, -) -> QueryResult { +pub fn entry_recursive(entry_id: &str, conn: Connection) -> QueryResult { use crate::database::schema::entries::dsl::entries; let entry: Entry = entries diff --git a/identity-api-rs/src/http/extractors/database.rs b/identity-api-rs/src/http/extractors/database.rs index 24e0ecf..3ba5274 100644 --- a/identity-api-rs/src/http/extractors/database.rs +++ b/identity-api-rs/src/http/extractors/database.rs @@ -2,13 +2,13 @@ use crate::AppState; use axum::{ async_trait, extract::FromRequestParts, - http::{header::AUTHORIZATION, request::Parts, StatusCode}, + http::{request::Parts, StatusCode}, }; use diesel::{ r2d2::{ConnectionManager, PooledConnection}, SqliteConnection, }; -use tracing::{error, warn}; +use tracing::error; pub struct Database(pub PooledConnection>); diff --git a/identity-api-rs/src/http/routes/auth.rs b/identity-api-rs/src/http/routes/auth.rs index 2350a18..74ae557 100644 --- a/identity-api-rs/src/http/routes/auth.rs +++ b/identity-api-rs/src/http/routes/auth.rs @@ -80,20 +80,18 @@ async fn genkey( use crate::database::schema::session_keys::dsl::*; let session_key = Uuid::new_v4().to_string(); - let result = diesel::insert_into(session_keys) + diesel::insert_into(session_keys) .values((user_id.eq(&user.uid), key.eq(&session_key))) - .execute(&mut conn); + .execute(&mut conn) + .map_err(|err| { + error!( + "failed to insert into session_keys {}, error: {err:?}", + user.uid + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; - if result.is_ok() { - Ok(Json(GenkeyResponse { session_key })) - } else { - error!( - "failed to insert into session_keys {}, error: {:?}", - user.uid, - result.err() - ); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + Ok(Json(GenkeyResponse { session_key })) } #[derive(Debug, Deserialize)] @@ -113,27 +111,26 @@ async fn login( ) -> Result, StatusCode> { if let Ok(Some(user)) = actions::user_by_email(&req.email, &mut conn) { let parsed_hash = PasswordHash::new(&user.password).expect("invalid argon2 password hash"); - if Argon2::default() + Argon2::default() .verify_password(req.password.as_bytes(), &parsed_hash) - .is_err() - { - info!("failed login attempt, invalid password: {}", &req.email); - Err(StatusCode::UNAUTHORIZED) - } else { - info!("valid login attempt: {}", req.email); - match encode_jwt(&JwtUser { - uid: user.id, - email: user.email, - name: user.name, - exp: expiration_time(), - }) { - Ok(token) => Ok(Json(LoginResponse { token })), - Err(err) => { - error!("token couldn't be encoded: {:?}", err); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } - } - } + .map_err(|_err| { + info!("failed login attempt, invalid password: {}", &req.email); + StatusCode::UNAUTHORIZED + })?; + + info!("valid login attempt: {}", req.email); + let token = encode_jwt(&JwtUser { + uid: user.id, + email: user.email, + name: user.name, + exp: expiration_time(), + }) + .map_err(|err| { + error!("token couldn't be encoded: {:?}", err); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok(Json(LoginResponse { token })) } else { info!("failed login attempt, email does not exist: {}", &req.email); Err(StatusCode::UNAUTHORIZED) @@ -159,85 +156,75 @@ async fn register( use crate::database::schema::limits::dsl as limits; use crate::database::schema::users::dsl as users; - let user = actions::user_by_email(&req.email, &mut conn); - - if user.is_err() { + let user = actions::user_by_email(&req.email, &mut conn).map_err(|err| { error!( - "failed to retrieve potential existing user from database: {}, error: {:?}", - &req.email, - user.err() + "failed to retrieve potential existing user from database: {}, error: {err:?}", + &req.email ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } + StatusCode::INTERNAL_SERVER_ERROR + })?; - if user.is_ok_and(|v| v.is_some()) { + if user.is_some() { info!("tried to register existing user: {}", &req.email); return Err(StatusCode::BAD_REQUEST); } let limit_id = Uuid::new_v4().to_string(); - let result = diesel::insert_into(limits::limits) + diesel::insert_into(limits::limits) .values(( limits::id.eq(&limit_id), limits::current_asset_count.eq(0), limits::max_asset_count.eq(10), )) - .execute(&mut conn); - - if result.is_err() { - error!( - "failed to insert into limits: {}, error: {:?}", - &req.email, - result.err() - ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } + .execute(&mut conn) + .map_err(|err| { + error!( + "failed to insert into limits: {}, error: {err:?}", + &req.email + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; let salt = SaltString::generate(&mut OsRng); let argon2 = Argon2::default(); - let password_hash = argon2.hash_password(req.password.as_bytes(), &salt); + let password_hash = argon2 + .hash_password(req.password.as_bytes(), &salt) + .map_err(|err| { + error!("failed to hash password: {err:?}"); + StatusCode::INTERNAL_SERVER_ERROR + })?; - if let Ok(password_hash) = password_hash { - let user_id = Uuid::new_v4().to_string(); - let result = diesel::insert_into(users::users) - .values(( - users::id.eq(&user_id), - users::created_at.eq(Utc::now().naive_utc()), - users::last_connected_at.eq(Utc::now().naive_utc()), - users::email.eq(&req.email), - users::password.eq(password_hash.to_string()), - users::name.eq(&req.name), - users::limits.eq(&limit_id), - // FIXME(sofia): Implement diesel::Expression for List - users::assets.eq("[]"), - )) - .execute(&mut conn); + let user_id = Uuid::new_v4().to_string(); + diesel::insert_into(users::users) + .values(( + users::id.eq(&user_id), + users::created_at.eq(Utc::now().naive_utc()), + users::last_connected_at.eq(Utc::now().naive_utc()), + users::email.eq(&req.email), + users::password.eq(password_hash.to_string()), + users::name.eq(&req.name), + users::limits.eq(&limit_id), + // FIXME(sofia): Implement diesel::Expression for List + users::assets.eq("[]"), + )) + .execute(&mut conn) + .map_err(|err| { + error!("failed to insert into users: {}, error: {err:?}", req.email); + StatusCode::INTERNAL_SERVER_ERROR + })?; - if result.is_err() { - error!( - "failed to insert into users: {}, error: {:?}", - req.email, - result.err() - ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } + let token = crate::auth::encode_jwt(&JwtUser { + uid: user_id, + email: req.email, + name: req.name, + exp: expiration_time(), + }) + .map_err(|err| { + error!("token couldn't be encoded: {:?}", err); + StatusCode::INTERNAL_SERVER_ERROR + })?; - match crate::auth::encode_jwt(&JwtUser { - uid: user_id, - email: req.email, - name: req.name, - exp: expiration_time(), - }) { - Ok(token) => Ok(Json(RegisterResponse { token })), - Err(err) => { - error!("token couldn't be encoded: {:?}", err); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } - } - } else { - error!("failed to hash password: {:?}", password_hash.err()); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + Ok(Json(RegisterResponse { token })) } #[derive(Debug, Serialize, Deserialize)] @@ -265,17 +252,16 @@ async fn list_heirs( Database(mut conn): Database, ExtractJwtUser(user): ExtractJwtUser, ) -> Result>, StatusCode> { - let result = actions::list_heirs(&user.uid, &mut conn); - if let Ok(heirs) = result { - Ok(Json(heirs.into_iter().map(HttpHeir::from).collect())) - } else { - error!( - "failed to obtain heirs: {}, error: {:?}", - user.uid, - result.err() - ); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + let heirs = actions::list_heirs(&user.uid, &mut conn) + .map_err(|err| { + error!( + "failed to obtain heirs: {}, error: {err:?}", + user.uid + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok(Json(heirs.into_iter().map(HttpHeir::from).collect())) } #[derive(Debug, Deserialize)] @@ -294,7 +280,7 @@ async fn insert_heir( use crate::database::schema::heirs::dsl::*; let heir_id = Uuid::new_v4().to_string(); - let result = diesel::insert_into(heirs) + diesel::insert_into(heirs) .values(( id.eq(heir_id), created_at.eq(Utc::now().naive_utc()), @@ -303,28 +289,25 @@ async fn insert_heir( // Only e-mail is implemented right now email.eq(req.value), )) - .execute(&mut conn); + .execute(&mut conn) + .map_err(|err| { + error!( + "failed to insert into heirs: {}, error: {err:?}", + user.uid + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; - if result.is_err() { - error!( - "failed to insert into heirs: {}, error: {:?}", - user.uid, - result.err() - ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } - - let result = actions::list_heirs(&user.uid, &mut conn); - if let Ok(heirs_list) = result { - Ok(Json(heirs_list.into_iter().map(HttpHeir::from).collect())) - } else { - error!( - "failed to obtain heirs: {}, error: {:?}", - user.uid, - result.err() - ); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + let heirs_list = actions::list_heirs(&user.uid, &mut conn) + .map_err(|err| { + error!( + "failed to obtain heirs: {}, error: {err:?}", + user.uid + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok(Json(heirs_list.into_iter().map(HttpHeir::from).collect())) } #[derive(Debug, Deserialize)] @@ -339,26 +322,24 @@ async fn delete_heir( ) -> Result>, StatusCode> { use crate::database::schema::heirs::dsl::*; - let result = diesel::delete(heirs.filter(id.eq(&req.id))).execute(&mut conn); - if result.is_err() { - error!( - "failed to delete from heirs: {}, heir_id: {}, error: {:?}", - user.uid, - req.id, - result.err() - ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } + diesel::delete(heirs.filter(id.eq(&req.id))).execute(&mut conn) + .map_err(|err| { + error!( + "failed to delete from heirs: {}, heir_id: {}, error: {err:?}", + user.uid, + req.id, + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; - let result = actions::list_heirs(&user.uid, &mut conn); - if let Ok(heirs_list) = result { - Ok(Json(heirs_list.into_iter().map(HttpHeir::from).collect())) - } else { - error!( - "failed to obtain heirs: {}, error: {:?}", - user.uid, - result.err() - ); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + let heirs_list = actions::list_heirs(&user.uid, &mut conn) + .map_err(|err| { + error!( + "failed to obtain heirs: {}, error: {err:?}", + user.uid, + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok(Json(heirs_list.into_iter().map(HttpHeir::from).collect())) } diff --git a/identity-api-rs/src/http/routes/entry.rs b/identity-api-rs/src/http/routes/entry.rs index 4cfd978..af91941 100644 --- a/identity-api-rs/src/http/routes/entry.rs +++ b/identity-api-rs/src/http/routes/entry.rs @@ -30,7 +30,7 @@ use crate::{ AppState, }; use axum::{ - extract::{Query, State}, + extract::Query, http::StatusCode, routing::{delete, get, put}, Json, Router, @@ -85,18 +85,18 @@ async fn list_entries( Query(query): Query, ExtractUser(user): ExtractUser, ) -> Result>, StatusCode> { - let result = actions::list_entries_recursive(&user.id, query.offset, query.limit, &mut conn); - if let Ok(entries) = result { - Ok(Json( - entries - .into_iter() - .filter_map(|v| HttpEntry::try_from(v).ok()) - .collect(), - )) - } else { - error!("failed to obtain entries {}: {:?}", user.id, result.err()); - Err(StatusCode::INTERNAL_SERVER_ERROR) - } + let entries = actions::list_entries_recursive(&user.id, query.offset, query.limit, &mut conn) + .map_err(|err| { + error!("failed to obtain entries {}: {err:?}", user.id); + StatusCode::INTERNAL_SERVER_ERROR + })?; + + Ok(Json( + entries + .into_iter() + .filter_map(|v| HttpEntry::try_from(v).ok()) + .collect(), + )) } #[derive(Debug, Deserialize)] @@ -115,8 +115,18 @@ async fn insert_entry( let entry = entry.entry; match entry.base { - HttpEntryBase::Album { ref artist, ref title, ref links, ref id } - | HttpEntryBase::Song { ref artist, ref title, ref links, ref id } => { + HttpEntryBase::Album { + ref artist, + ref title, + ref links, + ref id, + } + | HttpEntryBase::Song { + ref artist, + ref title, + ref links, + ref id, + } => { music_entry = Some(MusicEntry { id: Uuid::new_v4().to_string(), // FIXME(sofia): These clones seems unnecesary @@ -125,7 +135,7 @@ async fn insert_entry( artist: artist.clone(), universal_ids: id.clone().into(), }) - }, + } HttpEntryBase::Environment { ref location } => { if entry.title.as_ref().is_none_or(|v| v.is_empty()) { warn!( @@ -167,19 +177,19 @@ async fn insert_entry( HttpEntryBase::Date { ref referenced_date, } => { - let naive_date = NaiveDate::parse_from_str(referenced_date, "%Y-%m-%d"); - if let Err(err) = naive_date { - warn!( - "invalid date in request for inserting entry: {}, err: {err:?}", - user.id - ); - return Err(StatusCode::BAD_REQUEST); - } + let naive_date = NaiveDate::parse_from_str(referenced_date, "%Y-%m-%d") + .map_err(|err| { + warn!( + "invalid date in request for inserting entry: {}, err: {err:?}", + user.id + ); + StatusCode::BAD_REQUEST + })?; date_entry = Some(DateEntry { id: Uuid::new_v4().to_string(), referenced_date: NaiveDateTime::new( - naive_date.unwrap(), + naive_date, NaiveTime::from_hms_milli_opt(0, 0, 0, 0).unwrap(), ), }); @@ -216,26 +226,47 @@ async fn insert_entry( } let music_entry_id = music_entry.as_ref().map(|v| v.id.clone()); - music_entry.map(|music_entry| actions::insert_music_entry(&music_entry, &mut conn).map_err(|err| { - error!("failed to insert into music_entries: {}, error: {err:?}",user.id); - StatusCode::INTERNAL_SERVER_ERROR - })).transpose()?; + music_entry + .map(|music_entry| { + actions::insert_music_entry(&music_entry, &mut conn).map_err(|err| { + error!( + "failed to insert into music_entries: {}, error: {err:?}", + user.id + ); + StatusCode::INTERNAL_SERVER_ERROR + }) + }) + .transpose()?; let location_entry_id = location_entry.as_ref().map(|v| v.id.clone()); - location_entry.map(|location_entry| actions::insert_location_entry(&location_entry, &mut conn).map_err(|err| { - error!("failed to insert into location_entries: {}, error: {err:?}",user.id); - StatusCode::INTERNAL_SERVER_ERROR - })).transpose()?; + location_entry + .map(|location_entry| { + actions::insert_location_entry(&location_entry, &mut conn).map_err(|err| { + error!( + "failed to insert into location_entries: {}, error: {err:?}", + user.id + ); + StatusCode::INTERNAL_SERVER_ERROR + }) + }) + .transpose()?; let date_entry_id = date_entry.as_ref().map(|v| v.id.clone()); - date_entry.map(|date_entry| actions::insert_date_entry(&date_entry, &mut conn).map_err(|err| { - error!("failed to insert into date_entries: {}, error: {err:?}",user.id); - StatusCode::INTERNAL_SERVER_ERROR - })).transpose()?; + date_entry + .map(|date_entry| { + actions::insert_date_entry(&date_entry, &mut conn).map_err(|err| { + error!( + "failed to insert into date_entries: {}, error: {err:?}", + user.id + ); + StatusCode::INTERNAL_SERVER_ERROR + }) + }) + .transpose()?; { use crate::database::schema::entries::dsl as entries; - let result = diesel::insert_into(entries::entries) + diesel::insert_into(entries::entries) .values(( entries::id.eq(Uuid::new_v4().to_string()), entries::user_id.eq(&user.id), @@ -250,15 +281,14 @@ async fn insert_entry( entries::music_entry.eq(music_entry_id), entries::location_entry.eq(location_entry_id), )) - .execute(&mut conn); - - if let Err(err) = result { - error!( - "failed to insert into entries: {}, error: {:?}", - user.id, err - ); - return Err(StatusCode::INTERNAL_SERVER_ERROR); - } + .execute(&mut conn) + .map_err(|err| { + error!( + "failed to insert into entries: {}, error: {err:?}", + user.id + ); + StatusCode::INTERNAL_SERVER_ERROR + })?; } Ok(())