2023-02-19 17:56:01 +05:30
|
|
|
use crate::{
|
|
|
|
error::Error,
|
|
|
|
instance::DatabaseHandle,
|
|
|
|
objects::person::{DbUser, Person, PersonAcceptedActivities},
|
|
|
|
};
|
|
|
|
use activitypub_federation::{
|
2023-03-06 06:47:34 +05:30
|
|
|
axum::{
|
|
|
|
inbox::{receive_activity, ActivityData},
|
2023-03-17 02:11:29 +05:30
|
|
|
json::FederationJson,
|
2023-03-06 06:47:34 +05:30
|
|
|
},
|
2023-03-17 02:11:29 +05:30
|
|
|
config::{Data, FederationConfig, FederationMiddleware},
|
2023-03-06 06:47:34 +05:30
|
|
|
fetch::webfinger::{build_webfinger_response, extract_webfinger_name, Webfinger},
|
2023-02-19 17:56:01 +05:30
|
|
|
protocol::context::WithContext,
|
2023-03-17 02:11:29 +05:30
|
|
|
traits::Object,
|
2023-02-19 17:56:01 +05:30
|
|
|
};
|
|
|
|
use axum::{
|
2024-09-11 18:17:13 +05:30
|
|
|
debug_handler,
|
2023-03-02 04:49:10 +05:30
|
|
|
extract::{Path, Query},
|
2023-02-19 17:56:01 +05:30
|
|
|
response::IntoResponse,
|
|
|
|
routing::{get, post},
|
2023-07-03 18:35:18 +05:30
|
|
|
Json,
|
|
|
|
Router,
|
2023-02-19 17:56:01 +05:30
|
|
|
};
|
2023-03-02 04:49:10 +05:30
|
|
|
use serde::Deserialize;
|
2023-02-19 17:56:01 +05:30
|
|
|
use std::net::ToSocketAddrs;
|
2023-03-02 19:48:06 +05:30
|
|
|
use tracing::info;
|
2023-02-19 17:56:01 +05:30
|
|
|
|
2023-03-02 04:49:10 +05:30
|
|
|
pub fn listen(config: &FederationConfig<DatabaseHandle>) -> Result<(), Error> {
|
2023-03-08 03:31:36 +05:30
|
|
|
let hostname = config.domain();
|
2023-03-02 19:48:06 +05:30
|
|
|
info!("Listening with axum on {hostname}");
|
2023-03-02 04:49:10 +05:30
|
|
|
let config = config.clone();
|
2023-02-19 17:56:01 +05:30
|
|
|
let app = Router::new()
|
|
|
|
.route("/:user/inbox", post(http_post_user_inbox))
|
|
|
|
.route("/:user", get(http_get_user))
|
2023-03-02 04:49:10 +05:30
|
|
|
.route("/.well-known/webfinger", get(webfinger))
|
2023-03-17 02:11:29 +05:30
|
|
|
.layer(FederationMiddleware::new(config));
|
2023-02-19 17:56:01 +05:30
|
|
|
|
|
|
|
let addr = hostname
|
|
|
|
.to_socket_addrs()?
|
|
|
|
.next()
|
|
|
|
.expect("Failed to lookup domain name");
|
2024-09-11 18:17:13 +05:30
|
|
|
let fut = async move {
|
|
|
|
let listener = tokio::net::TcpListener::bind(addr).await.unwrap();
|
|
|
|
axum::serve(listener, app.into_make_service())
|
|
|
|
.await
|
|
|
|
.unwrap();
|
|
|
|
};
|
2023-02-19 17:56:01 +05:30
|
|
|
|
2024-09-11 18:17:13 +05:30
|
|
|
tokio::spawn(fut);
|
2023-02-19 17:56:01 +05:30
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2023-03-02 04:49:10 +05:30
|
|
|
#[debug_handler]
|
2023-02-19 17:56:01 +05:30
|
|
|
async fn http_get_user(
|
2023-03-02 04:49:10 +05:30
|
|
|
Path(name): Path<String>,
|
2023-03-16 06:41:48 +05:30
|
|
|
data: Data<DatabaseHandle>,
|
2023-03-17 02:11:29 +05:30
|
|
|
) -> Result<FederationJson<WithContext<Person>>, Error> {
|
2023-03-02 04:49:10 +05:30
|
|
|
let db_user = data.read_user(&name)?;
|
2023-03-17 02:11:29 +05:30
|
|
|
let json_user = db_user.into_json(&data).await?;
|
|
|
|
Ok(FederationJson(WithContext::new_default(json_user)))
|
2023-02-19 17:56:01 +05:30
|
|
|
}
|
|
|
|
|
2023-03-02 04:49:10 +05:30
|
|
|
#[debug_handler]
|
2023-02-19 17:56:01 +05:30
|
|
|
async fn http_post_user_inbox(
|
2023-03-16 06:41:48 +05:30
|
|
|
data: Data<DatabaseHandle>,
|
2023-02-19 17:56:01 +05:30
|
|
|
activity_data: ActivityData,
|
|
|
|
) -> impl IntoResponse {
|
|
|
|
receive_activity::<WithContext<PersonAcceptedActivities>, DbUser, DatabaseHandle>(
|
|
|
|
activity_data,
|
|
|
|
&data,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
}
|
2023-03-02 04:49:10 +05:30
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
struct WebfingerQuery {
|
|
|
|
resource: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[debug_handler]
|
|
|
|
async fn webfinger(
|
|
|
|
Query(query): Query<WebfingerQuery>,
|
2023-03-16 06:41:48 +05:30
|
|
|
data: Data<DatabaseHandle>,
|
2023-03-02 04:49:10 +05:30
|
|
|
) -> Result<Json<Webfinger>, Error> {
|
|
|
|
let name = extract_webfinger_name(&query.resource, &data)?;
|
2023-12-12 03:18:32 +05:30
|
|
|
let db_user = data.read_user(name)?;
|
2023-03-02 04:49:10 +05:30
|
|
|
Ok(Json(build_webfinger_response(
|
|
|
|
query.resource,
|
|
|
|
db_user.ap_id.into_inner(),
|
|
|
|
)))
|
|
|
|
}
|