this repo has no description
1use crate::auth::{extract_bearer_token_from_header, validate_bearer_token}; 2use crate::state::AppState; 3use axum::{ 4 Json, 5 body::Bytes, 6 extract::{Path, RawQuery, State}, 7 http::{HeaderMap, Method, StatusCode}, 8 response::{IntoResponse, Response}, 9}; 10use serde_json::json; 11 12pub async fn get_state( 13 State(state): State<AppState>, 14 headers: HeaderMap, 15 RawQuery(query): RawQuery, 16) -> Response { 17 if std::env::var("PDS_AGE_ASSURANCE_OVERRIDE").is_err() { 18 return proxy_to_appview(state, headers, "app.bsky.ageassurance.getState", query).await; 19 } 20 21 let created_at = get_account_created_at(&state, &headers).await; 22 let now = chrono::Utc::now().to_rfc3339(); 23 24 ( 25 StatusCode::OK, 26 Json(json!({ 27 "state": { 28 "status": "assured", 29 "access": "full", 30 "lastInitiatedAt": now 31 }, 32 "metadata": { 33 "accountCreatedAt": created_at 34 } 35 })), 36 ) 37 .into_response() 38} 39 40pub async fn get_age_assurance_state( 41 State(state): State<AppState>, 42 headers: HeaderMap, 43 RawQuery(query): RawQuery, 44) -> Response { 45 if std::env::var("PDS_AGE_ASSURANCE_OVERRIDE").is_err() { 46 return proxy_to_appview( 47 state, 48 headers, 49 "app.bsky.unspecced.getAgeAssuranceState", 50 query, 51 ) 52 .await; 53 } 54 55 (StatusCode::OK, Json(json!({"status": "assured"}))).into_response() 56} 57 58async fn get_account_created_at(state: &AppState, headers: &HeaderMap) -> Option<String> { 59 let auth_header = headers.get("Authorization").and_then(|h| h.to_str().ok()); 60 tracing::debug!(?auth_header, "age assurance: extracting token"); 61 62 let token = extract_bearer_token_from_header(auth_header)?; 63 tracing::debug!("age assurance: got token, validating"); 64 65 let auth_user = match validate_bearer_token(&state.db, &token).await { 66 Ok(user) => { 67 tracing::debug!(did = %user.did, "age assurance: validated user"); 68 user 69 } 70 Err(e) => { 71 tracing::warn!(?e, "age assurance: token validation failed"); 72 return None; 73 } 74 }; 75 76 let row = match sqlx::query!("SELECT created_at FROM users WHERE did = $1", auth_user.did) 77 .fetch_optional(&state.db) 78 .await 79 { 80 Ok(r) => { 81 tracing::debug!(?r, "age assurance: query result"); 82 r 83 } 84 Err(e) => { 85 tracing::warn!(?e, "age assurance: query failed"); 86 return None; 87 } 88 }; 89 90 row.map(|r| r.created_at.to_rfc3339()) 91} 92 93async fn proxy_to_appview( 94 state: AppState, 95 headers: HeaderMap, 96 method: &str, 97 query: Option<String>, 98) -> Response { 99 if headers.get("atproto-proxy").is_none() { 100 return ( 101 StatusCode::BAD_REQUEST, 102 Json(json!({ 103 "error": "InvalidRequest", 104 "message": "Missing required atproto-proxy header" 105 })), 106 ) 107 .into_response(); 108 } 109 110 crate::api::proxy::proxy_handler( 111 State(state), 112 Path(method.to_string()), 113 Method::GET, 114 headers, 115 RawQuery(query), 116 Bytes::new(), 117 ) 118 .await 119}