forked from alemi/upub
feat: handle host-meta and webfingers
This commit is contained in:
parent
efb1f506c3
commit
aab31eac67
4 changed files with 64 additions and 0 deletions
|
@ -20,3 +20,4 @@ tokio = { version = "1.35.1", features = ["full"] }
|
|||
tracing = "0.1.40"
|
||||
tracing-subscriber = "0.3.18"
|
||||
uuid = { version = "1.8.0", features = ["v4"] }
|
||||
jrd = "0.1"
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
pub mod user;
|
||||
pub mod object;
|
||||
pub mod activity;
|
||||
pub mod well_known;
|
||||
|
||||
pub mod jsonld;
|
||||
pub use jsonld::JsonLD;
|
||||
|
||||
|
|
58
src/activitypub/well_known.rs
Normal file
58
src/activitypub/well_known.rs
Normal file
|
@ -0,0 +1,58 @@
|
|||
use axum::{extract::{Query, State}, http::StatusCode, response::{IntoResponse, Response}};
|
||||
use jrd::{JsonResourceDescriptor, JsonResourceDescriptorLink};
|
||||
use sea_orm::EntityTrait;
|
||||
|
||||
use crate::{server::Context, model};
|
||||
|
||||
#[derive(Debug, serde::Deserialize)]
|
||||
pub struct WebfingerQuery {
|
||||
pub resource: String,
|
||||
}
|
||||
|
||||
pub struct JsonRD<T>(pub T);
|
||||
impl<T: serde::Serialize> IntoResponse for JsonRD<T> {
|
||||
fn into_response(self) -> Response {
|
||||
([("Content-Type", "application/jrd+json")], axum::Json(self.0)).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn webfinger(State(ctx): State<Context>, Query(query): Query<WebfingerQuery>) -> Result<JsonRD<JsonResourceDescriptor>, StatusCode> {
|
||||
if let Some((user, domain)) = query.resource.split_once('@') {
|
||||
let uid = ctx.uid(user.to_string());
|
||||
match model::user::Entity::find_by_id(uid)
|
||||
.one(ctx.db())
|
||||
.await
|
||||
{
|
||||
Ok(Some(x)) => Ok(JsonRD(JsonResourceDescriptor {
|
||||
subject: format!("acct:{user}@{domain}"),
|
||||
aliases: vec![x.id.clone()],
|
||||
links: vec![
|
||||
JsonResourceDescriptorLink {
|
||||
rel: "self".to_string(),
|
||||
link_type: Some("application/ld+json".to_string()),
|
||||
href: Some(x.id),
|
||||
properties: jrd::Map::default(),
|
||||
titles: jrd::Map::default(),
|
||||
},
|
||||
],
|
||||
expires: None,
|
||||
properties: jrd::Map::default(),
|
||||
})),
|
||||
Ok(None) => Err(StatusCode::NOT_FOUND),
|
||||
Err(e) => {
|
||||
tracing::error!("error executing webfinger query: {e}");
|
||||
Err(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
},
|
||||
}
|
||||
} else {
|
||||
Err(StatusCode::UNPROCESSABLE_ENTITY)
|
||||
}
|
||||
}
|
||||
|
||||
// i don't even want to bother with XML, im just returning a formatted xml string
|
||||
pub async fn host_meta(State(ctx): State<Context>) -> String {
|
||||
format!(r#"<?xml version="1.0" encoding="UTF-8"?>
|
||||
<XRD xmlns="http://docs.oasis-open.org/ns/xri/xrd-1.0">
|
||||
<Link type="application/xrd+xml" template="{}/.well-known/webfinger?resource={{uri}}" rel="lrdd" />
|
||||
</XRD>"#, ctx.base())
|
||||
}
|
|
@ -77,6 +77,9 @@ pub async fn serve(db: DatabaseConnection, domain: String) {
|
|||
.route("/", get(ap::view))
|
||||
.route("/inbox", post(ap::inbox))
|
||||
.route("/outbox", get(ap::outbox))
|
||||
// .well-known and discovery
|
||||
.route("/.well-known/webfinger", get(ap::well_known::webfinger))
|
||||
.route("/.well-known/host-meta", get(ap::well_known::host_meta))
|
||||
// actor routes
|
||||
.route("/users/:id", get(ap::user::view))
|
||||
.route("/users/:id/inbox", post(ap::user::inbox))
|
||||
|
|
Loading…
Reference in a new issue