fix: webfinger accepts full ids

thanks ari for helping me debug this! <3
This commit is contained in:
əlemi 2024-06-29 19:28:17 +02:00
parent 3fbff70933
commit a4df9f2fc0
Signed by: alemi
GPG key ID: A4895B84D311642C

View file

@ -3,6 +3,8 @@ use jrd::{JsonResourceDescriptor, JsonResourceDescriptorLink};
use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter}; use sea_orm::{ColumnTrait, EntityTrait, PaginatorTrait, QueryFilter};
use upub::{model, Context}; use upub::{model, Context};
use crate::ApiError;
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
pub struct NodeInfoDiscovery { pub struct NodeInfoDiscovery {
pub links: Vec<NodeInfoDiscoveryRel>, pub links: Vec<NodeInfoDiscoveryRel>,
@ -99,45 +101,59 @@ pub async fn webfinger(
State(ctx): State<Context>, State(ctx): State<Context>,
Query(query): Query<WebfingerQuery> Query(query): Query<WebfingerQuery>
) -> crate::ApiResult<JsonRD<JsonResourceDescriptor>> { ) -> crate::ApiResult<JsonRD<JsonResourceDescriptor>> {
if let Some((user, domain)) = query let user =
.resource if query.resource.starts_with("acct:") {
.replace("acct:", "") if let Some((user, domain)) = query
.split_once('@') .resource
{ .replace("acct:", "")
let usr = model::actor::Entity::find() .split_once('@')
.filter(model::actor::Column::PreferredUsername.eq(user)) {
.filter(model::actor::Column::Domain.eq(domain)) model::actor::Entity::find()
.one(ctx.db()) .filter(model::actor::Column::PreferredUsername.eq(user))
.await? .filter(model::actor::Column::Domain.eq(domain))
.ok_or_else(crate::ApiError::not_found)?; .one(ctx.db())
.await?
.ok_or_else(crate::ApiError::not_found)?
let expires = if domain == ctx.domain() { } else {
// TODO configurable webfinger TTL, also 30 days may be too much??? return Err(StatusCode::UNPROCESSABLE_ENTITY.into());
Some(chrono::Utc::now() + chrono::Duration::days(30)) }
} else if query.resource.starts_with("http") {
match model::actor::Entity::find_by_ap_id(&query.resource)
.one(ctx.db())
.await?
{
Some(usr) => usr,
None => return Err(ApiError::not_found()),
}
} else { } else {
// we are no authority on local users, this info should be considered already outdated, return Err(StatusCode::UNPROCESSABLE_ENTITY.into());
// but can still be relevant, for example for our frontend
Some(chrono::Utc::now())
}; };
Ok(JsonRD(JsonResourceDescriptor { let expires = if user.domain == ctx.domain() {
subject: format!("acct:{user}@{domain}"), // TODO configurable webfinger TTL, also 30 days may be too much???
aliases: vec![usr.id.clone()], Some(chrono::Utc::now() + chrono::Duration::days(30))
links: vec![
JsonResourceDescriptorLink {
rel: "self".to_string(),
link_type: Some("application/ld+json".to_string()),
href: Some(usr.id),
properties: jrd::Map::default(),
titles: jrd::Map::default(),
},
],
properties: jrd::Map::default(),
expires,
}))
} else { } else {
Err(StatusCode::UNPROCESSABLE_ENTITY.into()) // we are no authority on local users, this info should be considered already outdated,
} // but can still be relevant, for example for our frontend
Some(chrono::Utc::now())
};
Ok(JsonRD(JsonResourceDescriptor {
subject: format!("acct:{}@{}", user.preferred_username, user.domain),
aliases: vec![user.id.clone()],
links: vec![
JsonResourceDescriptorLink {
rel: "self".to_string(),
link_type: Some("application/ld+json".to_string()),
href: Some(user.id),
properties: jrd::Map::default(),
titles: jrd::Map::default(),
},
],
properties: jrd::Map::default(),
expires,
}))
} }
// i don't even want to bother with XML, im just returning a formatted xml string // i don't even want to bother with XML, im just returning a formatted xml string