hyaenidae/src/webfinger.rs
2021-04-02 12:07:19 -05:00

104 lines
3.7 KiB
Rust

use crate::{error::OptionExt, State};
use actix_web::{error::ResponseError, http::StatusCode, web, HttpResponse};
use actix_webfinger::{Resolver, Webfinger};
use futures::future::LocalBoxFuture;
use rsa::RSAPublicKey;
use rsa_magic_public_key::AsMagicPublicKey;
use rsa_pem::KeyExt;
pub(super) struct HyaenidaeResolver;
#[derive(Clone, Debug, thiserror::Error)]
#[error("Error resolving webfinger data")]
pub(super) struct ResolveError;
impl Resolver for HyaenidaeResolver {
type State = web::Data<State>;
type Error = ResolveError;
fn find(
handle: &str,
domain: &str,
state: Self::State,
) -> LocalBoxFuture<'static, Result<Option<Webfinger>, Self::Error>> {
let handle = handle.to_owned();
let domain = domain.to_owned();
Box::pin(async move {
if domain != state.domain {
return Ok(None);
}
let mut wf = Webfinger::new(&format!("{}@{}", handle, domain));
let wf = if handle == domain {
let server_store = state.profiles.store.servers.clone();
let apub_store = state.profiles.apub.clone();
web::block(move || {
let self_id = server_store.get_self()?.req()?;
let apub_id = apub_store.apub_for_server(self_id)?.req()?;
let key_id = apub_store.key_for_server(self_id)?.req()?;
let public_key = apub_store.public_key_for_id(&key_id)?.req()?;
let key = RSAPublicKey::from_pem_pkcs8(&public_key)?;
wf.add_activitypub(apub_id.as_str())
.add_magic_public_key(&key.as_magic_public_key());
Ok(wf) as Result<_, anyhow::Error>
})
.await
.map_err(|_| {
log::error!("Panic while finding server actor");
ResolveError
})?
.map_err(|e| {
log::error!("Failed to find server actor: {}", e);
ResolveError
})?
} else {
let profile_store = state.profiles.store.profiles.clone();
let apub_store = state.profiles.apub.clone();
web::block(move || {
let profile_id = profile_store.by_handle(&handle, &domain)?.req()?;
let apub_id = apub_store.apub_for_profile(profile_id)?.req()?;
let key_id = apub_store.key_for_profile(profile_id)?.req()?;
let public_key = apub_store.public_key_for_id(&key_id)?.req()?;
let key = RSAPublicKey::from_pem_pkcs8(&public_key)?;
let mut profile_url = apub_id.clone();
profile_url.set_path(&format!("/profiles/@{}@{}", handle, domain));
wf.add_activitypub(apub_id.as_str())
.add_magic_public_key(&key.as_magic_public_key())
.add_profile(profile_url.as_str());
Ok(wf) as Result<_, anyhow::Error>
})
.await
.map_err(|_| {
log::error!("Panic while finding profile actor");
ResolveError
})?
.map_err(|e| {
log::error!("Failed to find profile actor: {}", e);
ResolveError
})?
};
Ok(Some(wf))
})
}
}
impl ResponseError for ResolveError {
fn status_code(&self) -> StatusCode {
StatusCode::NOT_FOUND
}
fn error_response(&self) -> HttpResponse {
HttpResponse::NotFound().finish()
}
}