resolve did:web users
parent
c9e4db5f91
commit
28ecfd6851
78
src/user.rs
78
src/user.rs
|
@ -22,6 +22,28 @@ pub struct User {
|
|||
pub handle: Option<String>,
|
||||
}
|
||||
|
||||
fn create_user_from_did_doc(did_doc: DidDocument) -> Result<User> {
|
||||
let pds_endpoint = did_doc.get_pds_endpoint();
|
||||
let pds_uri: Option<Uri> = pds_endpoint.as_deref().unwrap_or_default().parse().ok();
|
||||
let pds = pds_uri
|
||||
.as_ref()
|
||||
.and_then(|u| u.authority())
|
||||
.map(|a| a.host())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
let handle = did_doc
|
||||
.also_known_as
|
||||
.and_then(|v| v.into_iter().next())
|
||||
.and_then(|s| s.strip_prefix("at://").map(str::to_string));
|
||||
let did = did_doc.id;
|
||||
|
||||
// TODO: check if handle resolves to did and fill none otherwise
|
||||
|
||||
let user = User { pds, did, handle };
|
||||
|
||||
Ok(user)
|
||||
}
|
||||
|
||||
pub async fn fetch_user(server: &RelayServer, did: &str) -> Result<User> {
|
||||
tracing::debug!(%did, "fetching user");
|
||||
if did.starts_with("did:plc:") {
|
||||
|
@ -58,29 +80,45 @@ pub async fn fetch_user(server: &RelayServer, did: &str) -> Result<User> {
|
|||
let did_doc = serde_json::from_reader::<_, DidDocument>(body.reader())
|
||||
.context("Failed to parse plc DID doc as JSON")?;
|
||||
|
||||
let pds_endpoint = did_doc.get_pds_endpoint();
|
||||
let pds_uri: Option<Uri> = pds_endpoint.as_deref().unwrap_or_default().parse().ok();
|
||||
let pds = pds_uri
|
||||
.as_ref()
|
||||
.and_then(|u| u.authority())
|
||||
.map(|a| a.host())
|
||||
.map(|s| s.to_string());
|
||||
|
||||
let handle = did_doc
|
||||
.also_known_as
|
||||
.and_then(|v| v.into_iter().next())
|
||||
.and_then(|s| s.strip_prefix("at://").map(str::to_string));
|
||||
let did = did_doc.id;
|
||||
|
||||
// TODO: check if handle resolves to did and fill none otherwise
|
||||
|
||||
let user = User { pds, did, handle };
|
||||
|
||||
let user = create_user_from_did_doc(did_doc)?;
|
||||
store_user(server, &user)?;
|
||||
|
||||
Ok(user)
|
||||
} else if let Some(domain) = did.strip_prefix("did:web:") {
|
||||
let tcp_stream = TcpStream::connect((domain, 443)).await?;
|
||||
let domain_tls: ServerName<'_> = ServerName::try_from(domain.to_string())?;
|
||||
let tls_stream = open_tls_stream(tcp_stream, domain_tls).await?;
|
||||
let io = TokioIo::new(tls_stream);
|
||||
|
||||
let req = Request::builder()
|
||||
.method("GET")
|
||||
.uri(format!("https://{domain}/.well-known/did.json"))
|
||||
.header("Host", domain.to_string())
|
||||
.body(body_empty())?;
|
||||
|
||||
let (mut sender, conn) = http1::handshake::<_, HttpBody>(io).await?;
|
||||
tokio::task::spawn(async move {
|
||||
if let Err(err) = conn.await {
|
||||
println!("Connection failed: {:?}", err);
|
||||
}
|
||||
});
|
||||
|
||||
let res = sender
|
||||
.send_request(req)
|
||||
.await
|
||||
.context("Failed to send plc request")?;
|
||||
if res.status() != StatusCode::OK {
|
||||
bail!("server returned non-200 status for did:web document");
|
||||
}
|
||||
|
||||
let body = res.collect().await?.aggregate();
|
||||
let did_doc = serde_json::from_reader::<_, DidDocument>(body.reader())
|
||||
.context("Failed to parse did:web document as JSON")?;
|
||||
|
||||
let user = create_user_from_did_doc(did_doc)?;
|
||||
store_user(server, &user)?;
|
||||
|
||||
Ok(user)
|
||||
} else if did.starts_with("did:web:") {
|
||||
todo!("resolve did web")
|
||||
} else {
|
||||
bail!("unknown did type {did}");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue