Skip to content

Commit

Permalink
add a test for #89
Browse files Browse the repository at this point in the history
  • Loading branch information
lovasoa committed Sep 18, 2023
1 parent 7ec9ced commit d08490d
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 23 deletions.
4 changes: 3 additions & 1 deletion src/filesystem.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ impl FileSystem {
for (i, component) in path.components().enumerate() {
if let Component::Normal(c) = component {
if !priviledged && i == 0 && c.eq_ignore_ascii_case("sqlpage") {
anyhow::bail!("Access to the sqlpage config directory is not allowed.");
anyhow::bail!(ErrorWithStatus {
status: actix_web::http::StatusCode::FORBIDDEN,
});
}
} else {
anyhow::bail!(
Expand Down
11 changes: 10 additions & 1 deletion src/webserver/error_with_status.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use actix_web::http::StatusCode;
use actix_web::{http::StatusCode, ResponseError};

#[derive(Debug, PartialEq)]
pub struct ErrorWithStatus {
Expand All @@ -10,3 +10,12 @@ impl std::fmt::Display for ErrorWithStatus {
}
}
impl std::error::Error for ErrorWithStatus {}

impl ResponseError for ErrorWithStatus {
fn status_code(&self) -> StatusCode {
self.status
}
fn error_response(&self) -> actix_web::HttpResponse {
actix_web::HttpResponse::build(self.status).body(self.status.to_string())
}
}
31 changes: 14 additions & 17 deletions src/webserver/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::webserver::database::{stream_query_results, DbItem};
use crate::webserver::ErrorWithStatus;
use crate::{AppState, Config, ParsedSqlFile};
use actix_web::dev::{fn_service, ServiceFactory, ServiceRequest};
use actix_web::error::{ErrorInternalServerError, ErrorNotFound};
use actix_web::error::ErrorInternalServerError;
use actix_web::http::header::{ContentType, Header, HttpDate, IfModifiedSince, LastModified};
use actix_web::http::{header, StatusCode, Uri};
use actix_web::web::Form;
Expand Down Expand Up @@ -411,24 +411,21 @@ async fn process_sql_request(
.sql_file_cache
.get(app_state, &sql_path)
.await
.map_err(|e| {
log::error!("Error while trying to get SQL file: {:#}", e);
if e.downcast_ref()
== Some(&ErrorWithStatus {
status: StatusCode::NOT_FOUND,
})
{
ErrorNotFound("The requested file was not found.")
} else {
ErrorInternalServerError(format!(
"An error occurred while trying to handle your request: {e:#}"
))
}
})?;
.map_err(anyhow_err_to_actix)?;
let response = render_sql(&mut req, sql_file).await?;
Ok(req.into_response(response))
}

fn anyhow_err_to_actix(e: anyhow::Error) -> actix_web::Error {
log::error!("Error while trying to get SQL file: {:#}", e);
match e.downcast::<ErrorWithStatus>() {
Ok(err) => actix_web::Error::from(err),
Err(e) => ErrorInternalServerError(format!(
"An error occurred while trying to handle your request: {e:#}"
)),
}
}

async fn serve_file(
path: &str,
state: &AppState,
Expand All @@ -441,7 +438,7 @@ async fn serve_file(
.file_system
.modified_since(state, path.as_ref(), since, false)
.await
.map_err(actix_web::error::ErrorBadRequest)?;
.map_err(anyhow_err_to_actix)?;
if !modified {
return Ok(HttpResponse::NotModified().finish());
}
Expand All @@ -450,7 +447,7 @@ async fn serve_file(
.file_system
.read_file(state, path.as_ref(), false)
.await
.map_err(actix_web::error::ErrorBadRequest)
.map_err(anyhow_err_to_actix)
.map(|b| {
HttpResponse::Ok()
.insert_header(
Expand Down
22 changes: 18 additions & 4 deletions tests/index.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
use actix_web::{
body::MessageBody,
http::{self, header::ContentType},
test,
};
use sqlpage::{app_config::AppConfig, webserver::http::main_handler, AppState};

#[actix_web::test]
async fn test_index_ok() {
let resp = req_path("/").await;
let resp = req_path("/").await.unwrap();
assert_eq!(resp.status(), http::StatusCode::OK);
let body = test::read_body(resp).await;
assert!(body.starts_with(b"<!DOCTYPE html>"));
Expand All @@ -16,7 +17,20 @@ async fn test_index_ok() {
assert!(!body.contains("error"));
}

async fn req_path(path: &str) -> actix_web::dev::ServiceResponse {
#[actix_web::test]
async fn test_access_config_forbidden() {
let resp_result = req_path("/sqlpage/sqlpage.json").await;
assert!(resp_result.is_err(), "Accessing the config file should be forbidden, but we received a response: {resp_result:?}");
let resp = resp_result.unwrap_err().error_response();
assert_eq!(resp.status(), http::StatusCode::FORBIDDEN);
assert!(
String::from_utf8_lossy(&resp.into_body().try_into_bytes().unwrap())
.to_lowercase()
.contains("forbidden"),
);
}

async fn req_path(path: &str) -> Result<actix_web::dev::ServiceResponse, actix_web::Error> {
init_log();
let config = test_config();
let state = AppState::init(&config).await.unwrap();
Expand All @@ -26,7 +40,7 @@ async fn req_path(path: &str) -> actix_web::dev::ServiceResponse {
.app_data(data)
.insert_header(ContentType::plaintext())
.to_srv_request();
main_handler(req).await.unwrap()
main_handler(req).await
}

pub fn test_config() -> AppConfig {
Expand All @@ -44,5 +58,5 @@ pub fn test_config() -> AppConfig {
}

fn init_log() {
env_logger::builder().is_test(true).try_init().unwrap();
let _ = env_logger::builder().is_test(true).try_init();
}

0 comments on commit d08490d

Please sign in to comment.