qol(http): replaced all explicit header setting with axum cookie jar
This commit is contained in:
Generated
+34
@@ -366,6 +366,28 @@ dependencies = [
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "axum-extra"
|
||||
version = "0.12.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "be44683b41ccb9ab2d23a5230015c9c3c55be97a25e4428366de8873103f7970"
|
||||
dependencies = [
|
||||
"axum",
|
||||
"axum-core",
|
||||
"bytes",
|
||||
"cookie",
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"http",
|
||||
"http-body",
|
||||
"http-body-util",
|
||||
"mime",
|
||||
"pin-project-lite",
|
||||
"tower-layer",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "base16ct"
|
||||
version = "0.2.0"
|
||||
@@ -682,6 +704,17 @@ version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2459377285ad874054d797f3ccebf984978aa39129f6eafde5cdc8315b612f8"
|
||||
|
||||
[[package]]
|
||||
name = "cookie"
|
||||
version = "0.18.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4ddef33a339a91ea89fb53151bd0a4689cfce27055c291dfa69945475d22c747"
|
||||
dependencies = [
|
||||
"percent-encoding",
|
||||
"time",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "core-foundation-sys"
|
||||
version = "0.8.7"
|
||||
@@ -2871,6 +2904,7 @@ dependencies = [
|
||||
"argon2",
|
||||
"async-broadcast",
|
||||
"axum",
|
||||
"axum-extra",
|
||||
"bytes",
|
||||
"chrono",
|
||||
"dashmap",
|
||||
|
||||
@@ -37,3 +37,4 @@ rubato = "3.0.0"
|
||||
chrono = "0.4.45"
|
||||
regex = "1"
|
||||
thiserror = "2.0.18"
|
||||
axum-extra = { version = "0.12.6", features = ["cookie"] }
|
||||
|
||||
+11
-38
@@ -6,6 +6,7 @@ use std::{
|
||||
},
|
||||
};
|
||||
|
||||
use axum_extra::extract::{CookieJar, cookie::Cookie};
|
||||
use regex::Regex;
|
||||
|
||||
// The Rust `regex` crate is guaranteed linear-time and therefore does NOT
|
||||
@@ -206,22 +207,6 @@ struct CreateStreamKeyBody {
|
||||
label: String,
|
||||
}
|
||||
|
||||
fn extract_session_token(headers: &HeaderMap) -> Option<String> {
|
||||
// Check bare `session` header first (curl / API clients)
|
||||
if let Some(v) = headers.get("session") {
|
||||
return Some(v.to_str().ok()?.to_string());
|
||||
}
|
||||
// Fall back to Cookie header (browsers)
|
||||
let cookie_header = headers.get("cookie")?.to_str().ok()?;
|
||||
cookie_header
|
||||
.split(';')
|
||||
.find_map(|pair| {
|
||||
let pair = pair.trim();
|
||||
pair.strip_prefix("session=")
|
||||
})
|
||||
.map(|v| v.to_string())
|
||||
}
|
||||
|
||||
struct AuthUser(entity::users::Model);
|
||||
|
||||
impl FromRequestParts<Arc<HttpServer>> for AuthUser {
|
||||
@@ -231,9 +216,10 @@ impl FromRequestParts<Arc<HttpServer>> for AuthUser {
|
||||
parts: &mut Parts,
|
||||
state: &Arc<HttpServer>,
|
||||
) -> Result<Self, HttpError> {
|
||||
let token = extract_session_token(&parts.headers).ok_or(HttpError::Unauthorized)?;
|
||||
let jar = CookieJar::from_request_parts(parts, state).await.unwrap();
|
||||
let session = jar.get("session").ok_or(HttpError::Unauthorized)?;
|
||||
|
||||
let user = users::Entity::find_by_auth_session(&state.db, token)
|
||||
let user = users::Entity::find_by_auth_session(&state.db, session.to_string())
|
||||
.await?
|
||||
.ok_or(HttpError::Unauthorized)?;
|
||||
|
||||
@@ -306,6 +292,7 @@ struct LoginResponse {
|
||||
async fn login_handler(
|
||||
State(state): State<Arc<HttpServer>>,
|
||||
Json(payload): Json<LoginForm>,
|
||||
jar: CookieJar,
|
||||
) -> Result<impl IntoResponse, HttpError> {
|
||||
let user = users::Entity::find_by_username(&state.db, payload.username.clone())
|
||||
.await?
|
||||
@@ -323,16 +310,8 @@ async fn login_handler(
|
||||
let auth = auth_session::Entity::create(&state.db, user.id).await?;
|
||||
let token = auth.value;
|
||||
|
||||
let mut meow = Response::new("".to_string());
|
||||
// TODO: Replace with axum cookie jar https://docs.rs/axum-extra/latest/axum_extra/extract/cookie/struct.CookieJar.html
|
||||
meow.headers_mut().insert(
|
||||
SET_COOKIE,
|
||||
format!("session={token}; SameSite=Strict; Path=/; Max-Age=2592000")
|
||||
.parse()
|
||||
.unwrap(),
|
||||
);
|
||||
*meow.status_mut() = StatusCode::OK;
|
||||
Ok(meow)
|
||||
let jar = jar.add(Cookie::new("session", token));
|
||||
Ok((StatusCode::OK, jar))
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
@@ -345,7 +324,8 @@ struct CreateUserForm {
|
||||
async fn create_user_handler(
|
||||
State(state): State<Arc<HttpServer>>,
|
||||
Json(payload): Json<CreateUserForm>,
|
||||
) -> Result<(HeaderMap, StatusCode), HttpError> {
|
||||
jar: CookieJar,
|
||||
) -> Result<impl IntoResponse, HttpError> {
|
||||
if state.config.signup_code.is_empty() || payload.ref_token != state.config.signup_code {
|
||||
warn!(username = %payload.username, "signup rejected: invalid signup code");
|
||||
return Err(HttpError::Unauthorized);
|
||||
@@ -372,15 +352,8 @@ async fn create_user_handler(
|
||||
let session = auth_session::Entity::create(&state.db, user.id).await?;
|
||||
let token = session.value;
|
||||
|
||||
let mut headers = HeaderMap::new();
|
||||
// TODO: Replace with axum cookie jar https://docs.rs/axum-extra/latest/axum_extra/extract/cookie/struct.CookieJar.html
|
||||
headers.insert(
|
||||
SET_COOKIE,
|
||||
format!("session={token}; HttpOnly; SameSite=Strict; Path=/")
|
||||
.parse()
|
||||
.unwrap(),
|
||||
);
|
||||
Ok((headers, StatusCode::OK))
|
||||
let jar = jar.add(Cookie::new("session", token));
|
||||
Ok((jar, StatusCode::OK))
|
||||
}
|
||||
|
||||
async fn stream_handler(
|
||||
|
||||
Reference in New Issue
Block a user