Skip to content

Commit

Permalink
Merge branch 'main' into docs-update-documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
kentSarmiento committed Dec 26, 2023
2 parents a4b6d05 + 06e91ac commit 097d877
Show file tree
Hide file tree
Showing 16 changed files with 430 additions and 176 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/development.yml
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ jobs:

- name: Generate and fix code coverage
run: |
cargo llvm-cov --ignore-filename-regex "main|inmemory" --lcov --output-path lcov.info
cargo llvm-cov --ignore-filename-regex "main" --lcov --output-path lcov.info
./rust-covfix lcov.info -o lcov.info
env:
RUST_TEST_THREADS: 1
Expand Down
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion link-for-later/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ futures = "0.3.29"
http-body-util = "0.1.0"
jsonwebtoken = "9.2.0"
mongodb = "2.8.0"
once_cell = "1.19.0"
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
tokio = { version = "1", features = ["macros"] }
Expand Down
15 changes: 6 additions & 9 deletions link-for-later/src/controller/auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,21 +20,18 @@ where
let TypedHeader(Authorization(bearer)) =
TypedHeader::<Authorization<Bearer>>::from_request_parts(parts, state)
.await
.map_err(|_| AppError::AuthorizationError)?;
.map_err(|_| {
AppError::AuthorizationError(String::from("Authorization token not found"))
})?;

let secret =
std::env::var(JWT_SECRET_KEY).map_or_else(|_| String::default(), |secret| secret);
let token_data = match decode::<Self>(
let token_data = decode::<Self>(
bearer.token(),
&DecodingKey::from_secret(secret.as_bytes()),
&Validation::default(),
) {
Ok(token) => token,
Err(e) => {
tracing::error!("Error: {}", e.to_string());
return Err(AppError::AuthorizationError);
}
};
)
.map_err(|e| AppError::AuthorizationError(format!("decode() {e:?}")))?;

Ok(token_data.claims)
}
Expand Down
97 changes: 90 additions & 7 deletions link-for-later/src/controller/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,45 @@ use serde_json::json;

use crate::types::AppError;

#[allow(clippy::cognitive_complexity)]
impl IntoResponse for AppError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
Self::ServerError | Self::DatabaseError(_) => {
Self::ServerError(ref e) => {
tracing::debug!("Server error: {}", e.to_string());
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
Self::LinkNotFound => (StatusCode::NOT_FOUND, self.to_string()),
Self::UserAlreadyExists
| Self::UserNotFound
| Self::InvalidEmail
| Self::InvalidUrl => (StatusCode::BAD_REQUEST, self.to_string()),
Self::AuthorizationError | Self::IncorrectPassword => {
Self::DatabaseError(ref e) => {
tracing::debug!("Database error: {}", e.to_string());
(StatusCode::INTERNAL_SERVER_ERROR, self.to_string())
}
Self::LinkNotFound(ref e) => {
tracing::debug!("Link not found: {}", e.to_string());
(StatusCode::NOT_FOUND, self.to_string())
}
Self::UserAlreadyExists(ref e) => {
tracing::debug!("User already exists: {}", e.to_string());
(StatusCode::BAD_REQUEST, self.to_string())
}
Self::UserNotFound(ref e) => {
tracing::debug!("User not found: {}", e.to_string());
(StatusCode::BAD_REQUEST, self.to_string())
}
Self::IncorrectPassword(ref e) => {
tracing::debug!("Incorrect password: {}", e.to_string());
(StatusCode::UNAUTHORIZED, self.to_string())
}
Self::AuthorizationError(ref e) => {
tracing::debug!("Authorization error: {}", e.to_string());
(StatusCode::UNAUTHORIZED, self.to_string())
}
Self::ValidationError(ref e) => {
tracing::debug!("Payload validation error: {}", e.to_string());
(StatusCode::BAD_REQUEST, self.to_string())
}

#[cfg(test)]
Self::TestError => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
};

let body = Json(json!({
Expand All @@ -30,3 +55,61 @@ impl IntoResponse for AppError {
(status, body).into_response()
}
}

#[cfg(test)]
mod tests {

use super::*;

#[test]
fn test_error_response() {
assert_eq!(
AppError::ServerError("a server operation failed".into())
.into_response()
.status(),
StatusCode::INTERNAL_SERVER_ERROR
);
assert_eq!(
AppError::DatabaseError("a database operation failed".into())
.into_response()
.status(),
StatusCode::INTERNAL_SERVER_ERROR
);
assert_eq!(
AppError::LinkNotFound("link".into())
.into_response()
.status(),
StatusCode::NOT_FOUND
);
assert_eq!(
AppError::UserAlreadyExists("user".into())
.into_response()
.status(),
StatusCode::BAD_REQUEST
);
assert_eq!(
AppError::UserNotFound("user".into())
.into_response()
.status(),
StatusCode::BAD_REQUEST
);
assert_eq!(
AppError::IncorrectPassword("user".into())
.into_response()
.status(),
StatusCode::UNAUTHORIZED
);
assert_eq!(
AppError::AuthorizationError("an authorization error occurred".into())
.into_response()
.status(),
StatusCode::UNAUTHORIZED
);
assert_eq!(
AppError::ValidationError("a validation error occurred".into())
.into_response()
.status(),
StatusCode::BAD_REQUEST
);
}
}
30 changes: 14 additions & 16 deletions link-for-later/src/controller/links.rs
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,7 @@ async fn post(
match payload.validate() {
Ok(()) => {}
Err(e) => {
tracing::error!("Error: {}", e);
return AppError::InvalidUrl.into_response();
return AppError::ValidationError(format!("post_link() {e:?}")).into_response();
}
}

Expand Down Expand Up @@ -105,8 +104,7 @@ async fn put(
match payload.validate() {
Ok(()) => {}
Err(e) => {
tracing::error!("Error: {}", e);
return AppError::InvalidUrl.into_response();
return AppError::ValidationError(format!("put_link() {e:?}")).into_response();
}
}

Expand Down Expand Up @@ -231,7 +229,7 @@ mod tests {
.expect_search()
.withf(move |_, query| query == &repo_query)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_links_service)).build();
let response = list(State(app_state), Claims::new("user-id", 0, 0)).await;
Expand All @@ -241,7 +239,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

#[traced_test]
Expand Down Expand Up @@ -301,7 +299,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "invalid url"}).to_string());
assert_eq!(body, json!({"error": "invalid request"}).to_string());
}

#[traced_test]
Expand All @@ -315,7 +313,7 @@ mod tests {
.expect_create()
.withf(move |_, item| item == &item_to_create)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_links_service)).build();
let response = post(
Expand All @@ -330,7 +328,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

#[traced_test]
Expand Down Expand Up @@ -378,7 +376,7 @@ mod tests {
.expect_get()
.withf(move |_, query| query == &repo_query)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_links_service)).build();
let response = get(
Expand All @@ -393,7 +391,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

#[traced_test]
Expand Down Expand Up @@ -458,7 +456,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "invalid url"}).to_string());
assert_eq!(body, json!({"error": "invalid request"}).to_string());
}

#[traced_test]
Expand All @@ -475,7 +473,7 @@ mod tests {
.expect_update()
.withf(move |_, id, item| id == "1" && item == &item_to_update)
.times(1)
.returning(|_, _, _| Err(AppError::ServerError));
.returning(|_, _, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_links_service)).build();
let response = put(
Expand All @@ -491,7 +489,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

#[traced_test]
Expand Down Expand Up @@ -528,7 +526,7 @@ mod tests {
.expect_delete()
.withf(move |_, item| item == &item_to_delete)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_links_service)).build();
let response = delete(
Expand All @@ -543,7 +541,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

struct AppStateBuilder {
Expand Down
18 changes: 8 additions & 10 deletions link-for-later/src/controller/users.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ async fn register(
match payload.validate() {
Ok(()) => {}
Err(e) => {
tracing::error!("Error: {}", e);
return AppError::InvalidEmail.into_response();
return AppError::ValidationError(format!("register() {e:?}")).into_response();
}
}

Expand All @@ -58,8 +57,7 @@ async fn login(
match payload.validate() {
Ok(()) => {}
Err(e) => {
tracing::error!("Error: {}", e);
return AppError::InvalidEmail.into_response();
return AppError::ValidationError(format!("login() {e:?}")).into_response();
}
}

Expand Down Expand Up @@ -141,7 +139,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "invalid email"}).to_string());
assert_eq!(body, json!({"error": "invalid request"}).to_string());
}

#[traced_test]
Expand All @@ -155,7 +153,7 @@ mod tests {
.expect_register()
.withf(move |_, user| user == &user_to_register)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_users_service)).build();
let response = register(State(app_state), Json(request)).await;
Expand All @@ -165,7 +163,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

#[traced_test]
Expand Down Expand Up @@ -209,7 +207,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "invalid email"}).to_string());
assert_eq!(body, json!({"error": "invalid request"}).to_string());
}

#[traced_test]
Expand All @@ -223,7 +221,7 @@ mod tests {
.expect_login()
.withf(move |_, user| user == &user_to_login)
.times(1)
.returning(|_, _| Err(AppError::ServerError));
.returning(|_, _| Err(AppError::TestError));

let app_state = AppStateBuilder::new(Arc::new(mock_users_service)).build();
let response = login(State(app_state), Json(request)).await;
Expand All @@ -233,7 +231,7 @@ mod tests {

let body = body.collect().await.unwrap().to_bytes();
let body = std::str::from_utf8(&body).unwrap();
assert_eq!(body, json!({"error": "server error"}).to_string());
assert_eq!(body, json!({"error": "test error"}).to_string());
}

struct AppStateBuilder {
Expand Down
Loading

0 comments on commit 097d877

Please sign in to comment.