diff --git a/slop-well-known/src/routes/webfinger.rs b/slop-well-known/src/routes/webfinger.rs index 114b0f9..4582858 100644 --- a/slop-well-known/src/routes/webfinger.rs +++ b/slop-well-known/src/routes/webfinger.rs @@ -2,9 +2,12 @@ use std::collections::HashMap; use axum::{Extension, Json}; use axum::extract::Query; +use axum::http::StatusCode; use axum::response::IntoResponse; +use sea_orm::{ColumnTrait, EntityTrait, QueryFilter}; use serde::{Deserialize, Serialize}; -use serde_with::skip_serializing_none; +use slop_common::db::entities::prelude::User; +use slop_common::db::entities::user; use slop_common::db::get_config; use slop_common::SlopState; @@ -14,22 +17,25 @@ pub struct WebfingerQuery { pub resource: String, } -#[skip_serializing_none] #[derive(Serialize)] -pub struct WebfingerRes { +pub struct Webfinger { pub subject: String, - pub aliases: Option>, + pub aliases: Vec, + #[serde(skip_serializing_if = "Option::is_none")] pub properties: Option>, - pub links: Option>, + pub links: Vec, } -#[skip_serializing_none] #[derive(Serialize)] pub struct Link { pub rel: String, - pub kind: Option, + #[serde(rename = "type", skip_serializing_if = "Option::is_none")] + pub mime: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub href: Option, + #[serde(skip_serializing_if = "Option::is_none")] pub titles: Option>, + #[serde(skip_serializing_if = "Option::is_none")] pub properties: Option>, } @@ -39,18 +45,51 @@ pub async fn webfinger( ) -> impl IntoResponse { let config = get_config(&state.conn).await; - Json(WebfingerRes { + if !query.resource.starts_with("acct:") { + return (StatusCode::BAD_REQUEST, "Unrecognized prefix").into_response() + } + + let subject: String = query.resource.chars().skip(5).collect(); + let subject: Vec<&str> = subject.splitn(2, "@").collect(); + + if subject[1] != config.domain { + return (StatusCode::NOT_FOUND, "Incorrect domain").into_response() + } + + let user: Option = User::find() + .filter(user::Column::Username.eq(subject[0])) + .one(&state.conn) + .await + .expect("Failed to access database!"); + + if user.is_none() { + return (StatusCode::NOT_FOUND, "User not found").into_response() + } + + let user = user.unwrap(); + + Json(Webfinger { subject: query.resource, - aliases: Some(vec![format!("https://{}/users/b", config.domain)]), + aliases: vec![ + format!("https://{}/@{}", config.domain, user.username), + format!("https://{}/users/{}", config.domain, user.id) + ], properties: None, - links: Some(vec![ + links: vec![ Link { - rel: "self".to_string(), - kind: Some(String::from("application/activity+json")), - href: Some(format!("https://{}/users/b", config.domain)), + rel: String::from("self"), + mime: Some(String::from("application/activity+json")), + href: Some(format!("https://{}/users/{}", config.domain, user.id)), + titles: None, + properties: None, + }, + Link { + rel: String::from("http://webfinger.net/rel/profile-page"), + mime: Some(String::from("text/html")), + href: Some(format!("https://{}/@{}", config.domain, user.username)), titles: None, properties: None, } - ]), - }) -} + ], + }).into_response() +} \ No newline at end of file