Compare commits

..

14 Commits

Author SHA1 Message Date
phundrak 7fe75bb559 style: format code
Publish Docker Images / build-docker (push) Successful in 5m38s
Publish Docker Images / coverage-and-sonar (push) Successful in 9m35s
Publish Docker Images / push-docker (push) Successful in 37s
2026-06-02 01:50:31 +02:00
phundrak b6d7c50a38 chore(audit): deny wildcard versions in Cargo.toml 2026-06-02 01:50:31 +02:00
phundrak 002ff9a1c5 feat(RateLimit): add Retry-After header for 429 errors 2026-06-02 01:50:31 +02:00
phundrak 6bc14c7429 fix(health): move test to dedicated test mod 2026-06-02 01:50:31 +02:00
phundrak 03592c1e83 refactor(RateLimitConfig): replace magic values with struct method 2026-06-02 01:50:31 +02:00
phundrak 6199e73e59 feat(contact): sanitize user-submitted data 2026-06-02 01:50:31 +02:00
phundrak 3c65e1d83d fix: typo 2026-06-02 01:50:31 +02:00
phundrak 7294cd7651 feat(logs): only activate json or pretty logs one at a time 2026-06-02 01:50:31 +02:00
phundrak 123c0d17ed refactor: simplify code 2026-06-02 01:50:31 +02:00
phundrak 7e074888a6 fix(contact): sanatize user-supplied data in logs 2026-06-02 01:50:31 +02:00
phundrak 215ac75721 fix(logs): make tracing target consistent 2026-06-02 01:50:31 +02:00
phundrak 4d3432e92f refactor: better value cloning 2026-06-02 01:50:31 +02:00
phundrak e3aaf05838 fix(RateLimit): apply rate limiting based on client IP 2026-06-02 01:50:31 +02:00
phundrak bb4e230c0d feat(settings): proper CORS in production
If the backend starts in production mode with no `frontend_url` is set,
immediately panic and stop.
2026-06-02 01:50:31 +02:00
3 changed files with 7 additions and 9 deletions
+1 -1
View File
@@ -54,7 +54,7 @@ impl Error for ContactError {}
/// issues beyond the client's control. /// issues beyond the client's control.
impl From<lettre::transport::smtp::Error> for ContactError { impl From<lettre::transport::smtp::Error> for ContactError {
fn from(value: lettre::transport::smtp::Error) -> Self { fn from(value: lettre::transport::smtp::Error) -> Self {
tracing::event!(target: "backend::contact", tracing::Level::ERROR, "SMTP Error details: {}", format!("{value:?}")); tracing::event!(target: "contact", tracing::Level::ERROR, "SMTP Error details: {}", format!("{value:?}"));
Self::OtherError(value.to_string()) Self::OtherError(value.to_string())
} }
} }
+2 -2
View File
@@ -186,6 +186,7 @@ impl ContactApi {
remote_addr: Option<poem::web::Data<&poem::web::RemoteAddr>>, remote_addr: Option<poem::web::Data<&poem::web::RemoteAddr>>,
) -> ContactApiResponse { ) -> ContactApiResponse {
let mut body = body.0; let mut body = body.0;
body.sanitize();
if let Some(ref honeypot) = body.honeypot if let Some(ref honeypot) = body.honeypot
&& !honeypot.trim().is_empty() && !honeypot.trim().is_empty()
{ {
@@ -197,7 +198,6 @@ impl ContactApi {
); );
return ContactApiResponse::Ok(ContactResponse::honeypot_response().into()); return ContactApiResponse::Ok(ContactResponse::honeypot_response().into());
} }
body.sanitize();
if let Err(e) = body.validate() { if let Err(e) = body.validate() {
return ContactApiResponse::BadRequest( return ContactApiResponse::BadRequest(
<validator::ValidationErrors as std::convert::Into<ContactResponse>>::into(e) <validator::ValidationErrors as std::convert::Into<ContactResponse>>::into(e)
@@ -251,7 +251,7 @@ impl ContactApi {
.subject(format!("Contact Form: {}", request.name)) .subject(format!("Contact Form: {}", request.name))
.header(ContentType::TEXT_PLAIN) .header(ContentType::TEXT_PLAIN)
.body(email_body)?; .body(email_body)?;
tracing::event!(target: "backend::contact", tracing::Level::DEBUG, "Email to be sent: {}", format!("{email:?}")); tracing::event!(target: "contact", tracing::Level::DEBUG, "Email to be sent: {}", format!("{email:?}"));
Ok(email) Ok(email)
} }
+4 -6
View File
@@ -84,12 +84,10 @@ impl From<Application> for RunnableApplication {
let cors = if value.settings.debug { let cors = if value.settings.debug {
Cors::new() Cors::new()
} else { } else {
if !cfg!(test) { assert!(
assert!( !cfg!(test) || !frontend_url.is_empty(),
!frontend_url.is_empty(), "CORS: frontend_url must be configured in production"
"CORS: frontend_url must be configured in production" );
);
}
Cors::new().allow_origin(frontend_url) Cors::new().allow_origin(frontend_url)
}; };
let app = value let app = value