-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
f47e3ae
commit a9ec8ae
Showing
8 changed files
with
198 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
use serde::{Deserialize, Serialize}; | ||
use uuid::Uuid; | ||
|
||
use super::{Email, Handle, User}; | ||
|
||
#[derive(Deserialize, Serialize)] | ||
pub struct GetUserResponse { | ||
id: Uuid, | ||
email: Email, | ||
handle: Handle, | ||
name: Option<String>, | ||
profile_photo: Option<String>, | ||
bio: Option<String>, | ||
} | ||
|
||
impl GetUserResponse { | ||
pub fn id(&self) -> Uuid { | ||
self.id | ||
} | ||
|
||
pub fn email(&self) -> Email { | ||
self.email.clone() | ||
} | ||
|
||
pub fn handle(&self) -> Handle { | ||
self.handle.clone() | ||
} | ||
|
||
pub fn name(&self) -> Option<String> { | ||
self.name.clone() | ||
} | ||
|
||
pub fn profile_photo(&self) -> Option<String> { | ||
self.profile_photo.clone() | ||
} | ||
|
||
pub fn bio(&self) -> Option<String> { | ||
self.bio.clone() | ||
} | ||
} | ||
|
||
impl From<User> for GetUserResponse { | ||
fn from(user: User) -> Self { | ||
GetUserResponse { | ||
id: user.id, | ||
email: user.email, | ||
handle: user.handle, | ||
name: user.name, | ||
profile_photo: user.profile_photo, | ||
bio: user.bio, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
pub mod health_check; | ||
pub mod middleware; | ||
pub mod server; | ||
pub mod user; | ||
pub mod user; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
use actix_web::{ | ||
web::{Data, Path}, | ||
HttpResponse, | ||
}; | ||
use sqlx::PgPool; | ||
use uuid::Uuid; | ||
|
||
use crate::{domain::user::GetUserResponse, storage}; | ||
|
||
#[tracing::instrument( | ||
name = "Getting user by ID", | ||
skip(user_id, db_pool), | ||
fields( | ||
id = %user_id, | ||
), | ||
)] | ||
pub async fn get_by_id(user_id: Path<Uuid>, db_pool: Data<PgPool>) -> HttpResponse { | ||
let id = user_id.into_inner(); | ||
|
||
match storage::get_user_by_id(&db_pool, id).await { | ||
Ok(user) => { | ||
if user.deleted_at().is_some() { | ||
let err = format!("user {} has been soft deleted", id); | ||
tracing::error!(err); | ||
HttpResponse::BadRequest().body(err) | ||
} else { | ||
let response: GetUserResponse = user.into(); | ||
let response_str = match serde_json::to_string(&response) { | ||
Ok(response_str) => response_str, | ||
Err(e) => { | ||
let err = format!("failed to parse user struct {} to json: {:?}", id, e); | ||
tracing::error!(err); | ||
return HttpResponse::InternalServerError().finish(); | ||
} | ||
}; | ||
HttpResponse::Ok().body(response_str) | ||
} | ||
} | ||
Err(e) => match e { | ||
sqlx::Error::RowNotFound => { | ||
let err = format!("user {} not found", id); | ||
tracing::error!(err); | ||
HttpResponse::NotFound().body(err) | ||
} | ||
e => { | ||
let err = format!("failed to get user {}: {:?}", id, e); | ||
tracing::error!(err); | ||
HttpResponse::InternalServerError().finish() | ||
} | ||
}, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
use claim::assert_ok; | ||
use fake::{faker::internet::en::SafeEmail, Fake}; | ||
use muttr_server::{ | ||
domain::user::{self, GetUserResponse}, | ||
handlers::user::BASE_PATH, | ||
}; | ||
use uuid::Uuid; | ||
|
||
use crate::utils::{ | ||
app::TestApp, | ||
http_client::{ContentType, Header, Path}, | ||
}; | ||
|
||
#[actix::test] | ||
async fn test_get_by_id_success() { | ||
let mut app = TestApp::spawn().await; | ||
|
||
for x in 1..6 { | ||
let email = assert_ok!( | ||
user::Email::try_from(SafeEmail().fake::<String>()), | ||
"failed to generated valid user email" | ||
); | ||
let handle = format!("test.user{}", x); | ||
let user = app | ||
.database | ||
.insert_user(email.as_ref(), &handle, true) | ||
.await; | ||
|
||
let response = app | ||
.client | ||
.request( | ||
Path::GET(format!("{}/{}", BASE_PATH, user.id())), | ||
&[Header::ContentType(ContentType::Json)], | ||
None::<String>, | ||
) | ||
.await; | ||
|
||
assert_eq!( | ||
200, | ||
response.status(), | ||
"The API did not return 200 on valid get user by id request: {}", | ||
response.text().await.unwrap_or_default(), | ||
); | ||
|
||
let user_res = match response.json::<GetUserResponse>().await { | ||
Ok(json) => json, | ||
Err(e) => panic!( | ||
"failed to unmarshal json from api response into GetUserResponse struct: {:?}", | ||
e | ||
), | ||
}; | ||
|
||
assert_eq!(user.id(), user_res.id(), "id does not match",); | ||
assert_eq!(user.email(), user_res.email(), "email does not match",); | ||
assert_eq!(user.handle(), user_res.handle(), "handle does not match",); | ||
assert_eq!(user.name(), user_res.name(), "name does not match",); | ||
assert_eq!( | ||
user.profile_photo(), | ||
user_res.profile_photo(), | ||
"profile_photo does not match", | ||
); | ||
assert_eq!(user.bio(), user_res.bio(), "bio does not match",); | ||
} | ||
} | ||
|
||
#[actix::test] | ||
async fn test_get_by_id_failure() { | ||
let app = TestApp::spawn().await; | ||
|
||
let id = Uuid::new_v4(); | ||
|
||
let user_res = app | ||
.client | ||
.request( | ||
Path::GET(format!("{}/{}", BASE_PATH, id)), | ||
&[Header::ContentType(ContentType::Json)], | ||
None::<String>, | ||
) | ||
.await; | ||
|
||
assert_eq!( | ||
404, | ||
user_res.status(), | ||
"The API did not return 404 when trying to GET a non-existant user id", | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
mod confirm; | ||
mod delete; | ||
mod get; | ||
mod login; | ||
mod patch; | ||
mod signup; | ||
|