improved tests
Some checks failed
CI/CD Pipeline / lint (push) Successful in 3m45s
CI/CD Pipeline / integration-tests (push) Failing after 55s
CI/CD Pipeline / unit-tests (push) Failing after 1m1s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped
Some checks failed
CI/CD Pipeline / lint (push) Successful in 3m45s
CI/CD Pipeline / integration-tests (push) Failing after 55s
CI/CD Pipeline / unit-tests (push) Failing after 1m1s
CI/CD Pipeline / e2e-tests (push) Has been skipped
CI/CD Pipeline / build (push) Has been skipped
This commit is contained in:
@@ -175,3 +175,140 @@ pub async fn run() -> anyhow::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use axum::{body::Body, http::Request, routing::get};
|
||||
use tower::ServiceExt;
|
||||
use std::sync::Mutex;
|
||||
|
||||
static ENV_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_cors_blocks_unknown_origin() {
|
||||
let _guard = ENV_LOCK.lock().unwrap();
|
||||
unsafe { std::env::set_var("ALLOWED_ORIGINS", "http://localhost:3000") };
|
||||
|
||||
let app = Router::new()
|
||||
.route("/test", get(|| async { "ok" }))
|
||||
.layer(
|
||||
CorsLayer::new()
|
||||
.allow_origin(parse_allowed_origins())
|
||||
.allow_methods([Method::GET])
|
||||
.allow_credentials(true),
|
||||
);
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method("OPTIONS")
|
||||
.uri("/test")
|
||||
.header("Origin", "http://evil.com")
|
||||
.header("Access-Control-Request-Method", "GET")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let acao = response
|
||||
.headers()
|
||||
.get("access-control-allow-origin")
|
||||
.map(|v| v.to_str().unwrap_or(""));
|
||||
assert!(acao.is_none() || acao == Some(""), "CORS should not allow http://evil.com");
|
||||
|
||||
unsafe { std::env::remove_var("ALLOWED_ORIGINS") };
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_cors_allows_configured_origin() {
|
||||
let _guard = ENV_LOCK.lock().unwrap();
|
||||
unsafe { std::env::set_var("ALLOWED_ORIGINS", "http://localhost:3000,http://mydomain.com") };
|
||||
|
||||
let app = Router::new()
|
||||
.route("/test", get(|| async { "ok" }))
|
||||
.layer(
|
||||
CorsLayer::new()
|
||||
.allow_origin(parse_allowed_origins())
|
||||
.allow_methods([Method::GET])
|
||||
.allow_credentials(true),
|
||||
);
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method("OPTIONS")
|
||||
.uri("/test")
|
||||
.header("Origin", "http://mydomain.com")
|
||||
.header("Access-Control-Request-Method", "GET")
|
||||
.body(Body::empty())
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let acao = response
|
||||
.headers()
|
||||
.get("access-control-allow-origin")
|
||||
.map(|v| v.to_str().unwrap_or(""));
|
||||
assert_eq!(acao, Some("http://mydomain.com"));
|
||||
|
||||
unsafe { std::env::remove_var("ALLOWED_ORIGINS") };
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_login_rejects_wrong_password() {
|
||||
let _guard = ENV_LOCK.lock().unwrap();
|
||||
unsafe { std::env::set_var("ADMIN_PASSWORD", "correct-horse-battery-staple") };
|
||||
|
||||
let admin_state = AdminAuthState::new();
|
||||
let app = Router::new()
|
||||
.route("/login", axum::routing::post(login_handler).with_state(admin_state));
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method("POST")
|
||||
.uri("/login")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(r#"{"password":"wrong"}"#))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::UNAUTHORIZED);
|
||||
unsafe { std::env::remove_var("ADMIN_PASSWORD") };
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_login_accepts_correct_password() {
|
||||
let _guard = ENV_LOCK.lock().unwrap();
|
||||
unsafe { std::env::set_var("ADMIN_PASSWORD", "correct-horse-battery-staple") };
|
||||
|
||||
let admin_state = AdminAuthState::new();
|
||||
let app = Router::new()
|
||||
.route("/login", axum::routing::post(login_handler).with_state(admin_state));
|
||||
|
||||
let response = app
|
||||
.oneshot(
|
||||
Request::builder()
|
||||
.method("POST")
|
||||
.uri("/login")
|
||||
.header("Content-Type", "application/json")
|
||||
.body(Body::from(r#"{"password":"correct-horse-battery-staple"}"#))
|
||||
.unwrap(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(response.status(), StatusCode::OK);
|
||||
let cookie = response.headers().get("set-cookie").unwrap().to_str().unwrap();
|
||||
assert!(cookie.contains("madbase_admin_session="));
|
||||
assert!(cookie.contains("HttpOnly"));
|
||||
assert!(cookie.contains("SameSite=Strict"));
|
||||
|
||||
unsafe { std::env::remove_var("ADMIN_PASSWORD") };
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user