Implement webfinger
This commit is contained in:
parent
25f299986b
commit
cb53a719eb
1 changed files with 55 additions and 16 deletions
|
|
@ -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<Vec<String>>,
|
||||
pub aliases: Vec<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<HashMap<String, String>>,
|
||||
pub links: Option<Vec<Link>>,
|
||||
pub links: Vec<Link>,
|
||||
}
|
||||
|
||||
#[skip_serializing_none]
|
||||
#[derive(Serialize)]
|
||||
pub struct Link {
|
||||
pub rel: String,
|
||||
pub kind: Option<String>,
|
||||
#[serde(rename = "type", skip_serializing_if = "Option::is_none")]
|
||||
pub mime: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub href: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub titles: Option<HashMap<String, String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub properties: Option<HashMap<String, String>>,
|
||||
}
|
||||
|
||||
|
|
@ -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::Model> = 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()
|
||||
}
|
||||
Loading…
Reference in a new issue