Parakeet is a Rust-based Bluesky AppServer aiming to implement most of the functionality required to support the Bluesky client
appview atproto bluesky rust appserver
66
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(parakeet): DID allowlist

Mia ed4aedf1 1c99beb2

+13 -2
+1
parakeet/src/config.rs
··· 23 23 pub plc_directory: Option<String>, 24 24 #[serde(default)] 25 25 pub cdn: ConfigCdn, 26 + pub did_allowlist: Option<Vec<String>>, 26 27 } 27 28 28 29 #[derive(Debug, Deserialize)]
+2
parakeet/src/main.rs
··· 18 18 pub index_client: parakeet_index::Client, 19 19 pub jwt: Arc<xrpc::jwt::JwtVerifier>, 20 20 pub cdn: Arc<xrpc::cdn::BskyCdn>, 21 + pub did_allowlist: Option<Vec<String>>, 21 22 } 22 23 23 24 #[tokio::main] ··· 69 70 index_client, 70 71 jwt, 71 72 cdn, 73 + did_allowlist: conf.did_allowlist, 72 74 }); 73 75 74 76 let addr = std::net::SocketAddr::new(conf.server.bind_address.parse()?, conf.server.port);
+2
parakeet/src/xrpc/com_atproto/identity.rs
··· 1 1 use crate::xrpc::error::XrpcResult; 2 + use crate::xrpc::extract::AtpAuth; 2 3 use crate::xrpc::get_actor_did; 3 4 use crate::GlobalState; 4 5 use axum::extract::{Query, State}; ··· 17 18 18 19 pub async fn resolve_handle( 19 20 State(state): State<GlobalState>, 21 + _auth: Option<AtpAuth>, 20 22 Query(query): Query<ResolveHandleQuery>, 21 23 ) -> XrpcResult<Json<ResolveHandleRes>> { 22 24 let did = get_actor_did(&state.dataloaders, query.handle).await?;
+8 -2
parakeet/src/xrpc/extract.rs
··· 82 82 .ok_or((StatusCode::UNAUTHORIZED, "missing JWT".to_string()))?; 83 83 84 84 match state.jwt.resolve_and_verify_jwt(hdr.token()).await { 85 - Some(claims) => Ok(AtpAuth(claims.iss)), 85 + Some(claims) => match &state.did_allowlist { 86 + Some(allowlist) if !allowlist.contains(&claims.iss) => Err((StatusCode::FORBIDDEN, "forbidden".to_string())), 87 + _ => Ok(AtpAuth(claims.iss)) 88 + }, 86 89 None => Err((StatusCode::INTERNAL_SERVER_ERROR, "JWT error".to_string())), 87 90 } 88 91 } ··· 106 109 }; 107 110 108 111 match state.jwt.resolve_and_verify_jwt(hdr.token()).await { 109 - Some(claims) => Ok(Some(AtpAuth(claims.iss))), 112 + Some(claims) => match &state.did_allowlist { 113 + Some(allowlist) if !allowlist.contains(&claims.iss) => Err((StatusCode::FORBIDDEN, "forbidden".to_string())), 114 + _ => Ok(Some(AtpAuth(claims.iss))) 115 + }, 110 116 None => Err((StatusCode::INTERNAL_SERVER_ERROR, "JWT error".to_string())), 111 117 } 112 118 }