feat(cors): implement CORS configuration with From trait
Implement From<CorsSettings> for Cors trait to configure CORS middleware with production-ready security validation. - Move CorsSettings to backend/src/settings/cors.rs module - Validate wildcard + credentials constraint (browser security policy) - Configure allowed methods, headers, credentials, and max_age - Add structured logging for CORS configuration - Move tests from settings/mod.rs and startup.rs to cors module Ref: T014
This commit is contained in:
@@ -225,131 +225,4 @@ mod tests {
|
||||
assert_eq!(app.host(), "127.0.0.1");
|
||||
assert_eq!(app.port(), 8080);
|
||||
}
|
||||
|
||||
// T013: Tests for build_cors() function (TDD - write tests FIRST)
|
||||
mod cors_tests {
|
||||
use super::*;
|
||||
use crate::settings::CorsSettings;
|
||||
|
||||
#[test]
|
||||
#[should_panic(expected = "CORS misconfiguration")]
|
||||
fn build_cors_with_credentials_and_wildcard_panics() {
|
||||
// GIVEN a CORS configuration with wildcard origin AND credentials enabled
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec!["*".to_string()],
|
||||
allow_credentials: true,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
// THEN it should panic with a clear error message
|
||||
let _cors = build_cors(&settings);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_with_wildcard_origin_creates_permissive_cors() {
|
||||
// GIVEN a CORS configuration with wildcard origin
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec!["*".to_string()],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should create a Cors middleware that allows any origin
|
||||
// Note: We can't directly test Cors behavior without integration tests
|
||||
// This test verifies that build_cors() completes without panicking
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_with_specific_origin_creates_restrictive_cors() {
|
||||
// GIVEN a CORS configuration with specific origins
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec![
|
||||
"https://sta.example.com".to_string(),
|
||||
"http://localhost:5173".to_string(),
|
||||
],
|
||||
allow_credentials: true,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should create a Cors middleware that only allows specified origins
|
||||
// Note: We can't directly test Cors behavior without integration tests
|
||||
// This test verifies that build_cors() completes without panicking
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_sets_correct_methods() {
|
||||
// GIVEN a CORS configuration
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec!["https://example.com".to_string()],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should configure the following methods:
|
||||
// GET, POST, PUT, PATCH, DELETE, OPTIONS
|
||||
// Note: Direct method verification requires integration tests
|
||||
// This test ensures build_cors() completes without errors
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_sets_correct_headers() {
|
||||
// GIVEN a CORS configuration
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec!["https://example.com".to_string()],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should configure the following headers:
|
||||
// content-type, authorization
|
||||
// Note: Direct header verification requires integration tests
|
||||
// This test ensures build_cors() completes without errors
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_sets_max_age_from_settings() {
|
||||
// GIVEN a CORS configuration with custom max_age
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec!["https://example.com".to_string()],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 7200, // 2 hours
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should configure max_age to 7200 seconds
|
||||
// Note: Direct max_age verification requires integration tests
|
||||
// This test ensures build_cors() completes without errors
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_cors_with_empty_origins() {
|
||||
// GIVEN a CORS configuration with no allowed origins (restrictive fail-safe)
|
||||
let settings = CorsSettings {
|
||||
allowed_origins: vec![],
|
||||
allow_credentials: false,
|
||||
max_age_secs: 3600,
|
||||
};
|
||||
|
||||
// WHEN build_cors() is called
|
||||
let _cors = build_cors(&settings);
|
||||
|
||||
// THEN it should create a Cors middleware that denies all origins
|
||||
// This test ensures build_cors() handles the fail-safe case
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user