diff --git a/migrations/postgres/20260320000000_create_instance_settings.sql b/migrations/postgres/20260320000000_create_instance_settings.sql --- a/migrations/postgres/20260320000000_create_instance_settings.sql +++ b/migrations/postgres/20260320000000_create_instance_settings.sql @@ -1,5 +1,5 @@ CREATE TABLE instance_settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL, - updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW() + updated_at TEXT NOT NULL DEFAULT (NOW()::text) ); diff --git a/src/xrpc/query.rs b/src/xrpc/query.rs --- a/src/xrpc/query.rs +++ b/src/xrpc/query.rs @@ -34,15 +34,19 @@ })?; let limit: i64 = params .get("limit") - .and_then(|v| v.as_str()) - .and_then(|l| l.parse().ok()) + .and_then(|v| { + v.as_i64() + .or_else(|| v.as_str().and_then(|s| s.parse().ok())) + }) .unwrap_or(20) .min(100); let offset: i64 = params .get("cursor") - .and_then(|v| v.as_str()) - .and_then(|c| c.parse().ok()) + .and_then(|v| { + v.as_i64() + .or_else(|| v.as_str().and_then(|s| s.parse().ok())) + }) .unwrap_or(0); let did = params.get("did").and_then(|v| v.as_str()); diff --git a/tests/common/auth.rs b/tests/common/auth.rs --- a/tests/common/auth.rs +++ b/tests/common/auth.rs @@ -1,4 +1,5 @@ use axum::http::{HeaderName, HeaderValue}; +use axum::response::IntoResponse; use axum_extra::extract::cookie::{Cookie, Key, SignedCookieJar}; /// Build a Cookie header containing a signed session cookie for the given DID. @@ -9,12 +10,20 @@ let mut cookie = Cookie::new(happyview::auth::COOKIE_NAME, did.to_string()); cookie.set_path("/"); let jar = jar.add(cookie); - // Extract the Set-Cookie value and convert to a Cookie request header - let cookie_header = jar + // Build a response to extract the Set-Cookie header with the signed value, + // then convert it to a Cookie request header. + let response = jar.into_response(); + let set_cookie_values: Vec = response + .headers() + .get_all("set-cookie") .iter() - .map(|c| format!("{}={}", c.name(), c.value())) - .collect::>() - .join("; "); + .filter_map(|v| { + let s = v.to_str().ok()?; + // Extract just "name=value" from "name=value; Path=/; ..." + Some(s.split(';').next()?.to_string()) + }) + .collect(); + let cookie_header = set_cookie_values.join("; "); ( HeaderName::from_static("cookie"), diff --git a/tests/e2e_xrpc.rs b/tests/e2e_xrpc.rs --- a/tests/e2e_xrpc.rs +++ b/tests/e2e_xrpc.rs @@ -36,14 +36,6 @@ .body(Body::from(serde_json::to_vec(body).unwrap())) .unwrap() } -fn authed_get(uri: &str, token: &str) -> Request { - Request::builder() - .uri(uri) - .header("authorization", format!("Bearer {token}")) - .body(Body::empty()) - .unwrap() -} - async fn seed_lexicons(app: &TestApp) { // Record lexicon app.router @@ -141,7 +133,7 @@ #[serial] #[ignore] async fn profile_with_mocked_services_returns_200() { let app = TestApp::new().await; - let did = "did:plc:testuser"; + let did = &app.admin_did; // Mock PLC directory Mock::given(method("GET")) @@ -160,16 +152,23 @@ .respond_with(ResponseTemplate::new(200).set_body_json(fixtures::profile_record())) .mount(&app.mock_server) .await; + let cookie = app.admin_cookie(); let resp = app .router .clone() - .oneshot(authed_get("/xrpc/app.bsky.actor.getProfile", "valid-token")) + .oneshot( + Request::builder() + .uri("/xrpc/app.bsky.actor.getProfile") + .header(cookie.0, cookie.1) + .body(Body::empty()) + .unwrap(), + ) .await .unwrap(); assert_eq!(resp.status(), StatusCode::OK); let json = json_body(resp).await; - assert_eq!(json["did"], did); + assert_eq!(json["did"], did.as_str()); assert_eq!(json["displayName"], "Test User"); }