2023-02-19 17:56:01 +05:30
|
|
|
use crate::{
|
|
|
|
error::Error,
|
|
|
|
instance::DatabaseHandle,
|
|
|
|
objects::person::{DbUser, PersonAcceptedActivities},
|
|
|
|
};
|
|
|
|
use activitypub_federation::{
|
2023-03-02 04:49:10 +05:30
|
|
|
config::{ApubMiddleware, FederationConfig, RequestData},
|
2023-02-19 17:56:01 +05:30
|
|
|
core::actix_web::inbox::receive_activity,
|
|
|
|
protocol::context::WithContext,
|
|
|
|
traits::ApubObject,
|
2023-03-02 04:49:10 +05:30
|
|
|
webfinger::{build_webfinger_response, extract_webfinger_name},
|
2023-02-19 17:56:01 +05:30
|
|
|
APUB_JSON_CONTENT_TYPE,
|
|
|
|
};
|
|
|
|
use actix_web::{web, web::Bytes, App, HttpRequest, HttpResponse, HttpServer};
|
|
|
|
use anyhow::anyhow;
|
2023-03-02 04:49:10 +05:30
|
|
|
use serde::Deserialize;
|
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> {
|
|
|
|
let hostname = config.hostname();
|
2023-03-02 19:48:06 +05:30
|
|
|
info!("Listening with actix-web on {hostname}");
|
2023-03-02 04:49:10 +05:30
|
|
|
let config = config.clone();
|
2023-02-19 17:56:01 +05:30
|
|
|
let server = HttpServer::new(move || {
|
|
|
|
App::new()
|
2023-03-02 04:49:10 +05:30
|
|
|
.wrap(ApubMiddleware::new(config.clone()))
|
2023-02-19 17:56:01 +05:30
|
|
|
.route("/{user}", web::get().to(http_get_user))
|
|
|
|
.route("/{user}/inbox", web::post().to(http_post_user_inbox))
|
2023-03-02 04:49:10 +05:30
|
|
|
.route("/.well-known/webfinger", web::get().to(webfinger))
|
2023-02-19 17:56:01 +05:30
|
|
|
})
|
|
|
|
.bind(hostname)?
|
|
|
|
.run();
|
|
|
|
actix_rt::spawn(server);
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles requests to fetch user json over HTTP
|
|
|
|
pub async fn http_get_user(
|
|
|
|
user_name: web::Path<String>,
|
|
|
|
data: RequestData<DatabaseHandle>,
|
|
|
|
) -> Result<HttpResponse, Error> {
|
|
|
|
let db_user = data.local_user();
|
|
|
|
if user_name.into_inner() == db_user.name {
|
|
|
|
let apub_user = db_user.into_apub(&data).await?;
|
|
|
|
Ok(HttpResponse::Ok()
|
|
|
|
.content_type(APUB_JSON_CONTENT_TYPE)
|
|
|
|
.json(WithContext::new_default(apub_user)))
|
|
|
|
} else {
|
|
|
|
Err(anyhow!("Invalid user").into())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Handles messages received in user inbox
|
|
|
|
pub async fn http_post_user_inbox(
|
|
|
|
request: HttpRequest,
|
|
|
|
body: Bytes,
|
|
|
|
data: RequestData<DatabaseHandle>,
|
|
|
|
) -> Result<HttpResponse, Error> {
|
|
|
|
receive_activity::<WithContext<PersonAcceptedActivities>, DbUser, DatabaseHandle>(
|
|
|
|
request, body, &data,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
}
|
2023-03-02 04:49:10 +05:30
|
|
|
|
|
|
|
#[derive(Deserialize)]
|
|
|
|
pub struct WebfingerQuery {
|
|
|
|
resource: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
pub async fn webfinger(
|
|
|
|
query: web::Query<WebfingerQuery>,
|
|
|
|
data: RequestData<DatabaseHandle>,
|
|
|
|
) -> Result<HttpResponse, Error> {
|
|
|
|
let name = extract_webfinger_name(&query.resource, &data)?;
|
|
|
|
let db_user = data.read_user(&name)?;
|
|
|
|
Ok(HttpResponse::Ok().json(build_webfinger_response(
|
|
|
|
query.resource.clone(),
|
|
|
|
db_user.ap_id.into_inner(),
|
|
|
|
)))
|
|
|
|
}
|