mirror of
https://github.com/block/buzz.git
synced 2026-10-27 04:30:52 +00:00
Signed-off-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1ntr8jjcqq6gt06q5avvqttfjgpwshmra22pcmcagdnukw4ja4nqqsa9g54 <9ac6794b000690b7e814eb1805ad32405d0bec7d52838de3a86cf967565dacc0@sprout-oss.stage.blox.sqprod.co> Co-authored-by: npub1dccv64krpcpse5cmkzfeh998cftungyatw3djt8jwdw6g43f7fyqzzmrf7 <6e30cd56c30e030cd31bb0939b94a7c257c9a09d5ba2d92cf2735da45629f248@sprout-oss.stage.blox.sqprod.co>
63 lines
1.6 KiB
Rust
63 lines
1.6 KiB
Rust
use axum::http::{header, HeaderMap};
|
|
|
|
use super::error::ApiError;
|
|
use crate::state::AppState;
|
|
|
|
pub(crate) fn is_admin_host(state: &AppState, headers: &HeaderMap) -> bool {
|
|
let Some(config) = state.config.admin.as_ref() else {
|
|
return false;
|
|
};
|
|
headers
|
|
.get(header::HOST)
|
|
.and_then(|value| value.to_str().ok())
|
|
.is_some_and(|host| host == config.host)
|
|
}
|
|
|
|
pub fn authorize(state: &AppState, headers: &HeaderMap) -> Result<(), ApiError> {
|
|
let config = state
|
|
.config
|
|
.admin
|
|
.as_ref()
|
|
.ok_or_else(ApiError::not_found)?;
|
|
if !is_admin_host(state, headers) {
|
|
return Err(ApiError::forbidden());
|
|
}
|
|
if headers.get(header::ORIGIN).is_some_and(|origin| {
|
|
origin
|
|
.to_str()
|
|
.map_or(true, |origin| !origin_matches_host(origin, &config.host))
|
|
}) {
|
|
return Err(ApiError::forbidden());
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
fn origin_matches_host(origin: &str, host: &str) -> bool {
|
|
origin
|
|
.strip_prefix("https://")
|
|
.or_else(|| origin.strip_prefix("http://"))
|
|
== Some(host)
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::origin_matches_host;
|
|
|
|
#[test]
|
|
fn browser_origin_must_match_admin_host() {
|
|
assert!(origin_matches_host(
|
|
"https://admin.example.com",
|
|
"admin.example.com"
|
|
));
|
|
assert!(origin_matches_host(
|
|
"http://admin.localhost:3000",
|
|
"admin.localhost:3000"
|
|
));
|
|
assert!(!origin_matches_host(
|
|
"https://attacker.example",
|
|
"admin.example.com"
|
|
));
|
|
assert!(!origin_matches_host("null", "admin.example.com"));
|
|
}
|
|
}
|