Remove federation functionality and related tests
- Deleted the `federation.rs` module and its associated functionality for federating thoughts to followers. - Removed the `well_known.rs` module and its WebFinger discovery functionality. - Eliminated references to federation in the `thought.rs` router and removed the spawning of background tasks for federating thoughts. - Deleted tests related to WebFinger and user inbox interactions in `activitypub.rs`. - Updated `Cargo.toml` to remove the `activitypub_federation` dependency.
This commit is contained in:
@@ -1,70 +0,0 @@
|
||||
use app::{
|
||||
persistence::{follow, user},
|
||||
state::AppState,
|
||||
};
|
||||
use models::domains::thought;
|
||||
use serde_json::json;
|
||||
|
||||
// This function handles pushing a new thought to all followers.
|
||||
pub async fn federate_thought(
|
||||
state: AppState,
|
||||
thought: thought::Model,
|
||||
author: models::domains::user::Model,
|
||||
) {
|
||||
// Find all followers of the author
|
||||
let follower_ids = match follow::get_follower_ids(&state.conn, author.id).await {
|
||||
Ok(ids) => ids,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to get followers for federation: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
if follower_ids.is_empty() {
|
||||
println!("No followers to federate to for user {}", author.username);
|
||||
return;
|
||||
}
|
||||
|
||||
let thought_url = format!("{}/thoughts/{}", &state.base_url, thought.id);
|
||||
let author_url = format!("{}/users/{}", &state.base_url, author.username);
|
||||
|
||||
// Construct the "Create" activity containing the "Note" object
|
||||
let activity = json!({
|
||||
"@context": "https://www.w3.org/ns/activitystreams",
|
||||
"id": format!("{}/activity", thought_url),
|
||||
"type": "Create",
|
||||
"actor": author_url,
|
||||
"object": {
|
||||
"id": thought_url,
|
||||
"type": "Note",
|
||||
"attributedTo": author_url,
|
||||
"content": thought.content,
|
||||
"published": thought.created_at.to_rfc3339(),
|
||||
"to": ["https://www.w3.org/ns/activitystreams#Public"],
|
||||
"cc": [format!("{}/followers", author_url)]
|
||||
}
|
||||
});
|
||||
|
||||
// Get the inbox URLs for all followers
|
||||
// In a real federated app, you would store remote users' full inbox URLs.
|
||||
// For now, we assume followers are local and construct their inbox URLs.
|
||||
let followers = match user::get_users_by_ids(&state.conn, follower_ids).await {
|
||||
Ok(users) => users,
|
||||
Err(e) => {
|
||||
tracing::error!("Failed to get follower user objects: {}", e);
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
let client = reqwest::Client::new();
|
||||
for follower in followers {
|
||||
let inbox_url = format!("{}/users/{}/inbox", &state.base_url, follower.username);
|
||||
tracing::info!("Federating post {} to {}", thought.id, inbox_url);
|
||||
|
||||
let res = client.post(&inbox_url).json(&activity).send().await;
|
||||
|
||||
if let Err(e) = res {
|
||||
tracing::error!("Failed to federate to {}: {}", inbox_url, e);
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,5 @@
|
||||
mod error;
|
||||
mod extractor;
|
||||
mod federation;
|
||||
mod init;
|
||||
mod validation;
|
||||
|
||||
|
@@ -9,9 +9,8 @@ pub mod search;
|
||||
pub mod tag;
|
||||
pub mod thought;
|
||||
pub mod user;
|
||||
pub mod well_known;
|
||||
|
||||
use crate::routers::{auth::create_auth_router, well_known::create_well_known_router};
|
||||
use crate::routers::auth::create_auth_router;
|
||||
use app::state::AppState;
|
||||
use root::create_root_router;
|
||||
use tower_http::cors::CorsLayer;
|
||||
@@ -24,7 +23,6 @@ pub fn create_router(state: AppState) -> Router {
|
||||
|
||||
Router::new()
|
||||
.merge(create_root_router())
|
||||
.nest("/.well-known", create_well_known_router())
|
||||
.nest("/auth", create_auth_router())
|
||||
.nest("/users", create_user_router())
|
||||
.nest("/thoughts", create_thought_router())
|
||||
|
@@ -20,7 +20,6 @@ use sea_orm::prelude::Uuid;
|
||||
use crate::{
|
||||
error::ApiError,
|
||||
extractor::{AuthUser, Json, OptionalAuthUser, Valid},
|
||||
federation,
|
||||
models::{ApiErrorResponse, ParamsErrorResponse},
|
||||
};
|
||||
|
||||
@@ -77,13 +76,6 @@ async fn thoughts_post(
|
||||
.await?
|
||||
.ok_or(UserError::NotFound)?; // Should not happen if auth is valid
|
||||
|
||||
// Spawn a background task to handle federation without blocking the response
|
||||
tokio::spawn(federation::federate_thought(
|
||||
state.clone(),
|
||||
thought.clone(),
|
||||
author.clone(),
|
||||
));
|
||||
|
||||
let schema = ThoughtSchema::from_models(&thought, &author);
|
||||
Ok((StatusCode::CREATED, Json(schema)))
|
||||
}
|
||||
|
@@ -1,70 +0,0 @@
|
||||
use app::state::AppState;
|
||||
use axum::{
|
||||
extract::{Query, State},
|
||||
response::{IntoResponse, Json},
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use url::Url;
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct WebFingerQuery {
|
||||
resource: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct WebFingerLink {
|
||||
rel: String,
|
||||
#[serde(rename = "type")]
|
||||
type_: String,
|
||||
href: Url,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
pub struct WebFingerResponse {
|
||||
subject: String,
|
||||
links: Vec<WebFingerLink>,
|
||||
}
|
||||
|
||||
pub async fn webfinger(
|
||||
State(state): State<AppState>,
|
||||
Query(query): Query<WebFingerQuery>,
|
||||
) -> Result<impl IntoResponse, impl IntoResponse> {
|
||||
if let Some((scheme, account_info)) = query.resource.split_once(':') {
|
||||
if scheme != "acct" {
|
||||
return Err((
|
||||
axum::http::StatusCode::BAD_REQUEST,
|
||||
"Invalid resource scheme",
|
||||
));
|
||||
}
|
||||
|
||||
let account_parts: Vec<&str> = account_info.split('@').collect();
|
||||
let username = account_parts[0];
|
||||
|
||||
let user = match app::persistence::user::get_user_by_username(&state.conn, username).await {
|
||||
Ok(Some(user)) => user,
|
||||
_ => return Err((axum::http::StatusCode::NOT_FOUND, "User not found")),
|
||||
};
|
||||
|
||||
let user_url = Url::parse(&format!("{}/users/{}", &state.base_url, user.username)).unwrap();
|
||||
|
||||
let response = WebFingerResponse {
|
||||
subject: query.resource,
|
||||
links: vec![WebFingerLink {
|
||||
rel: "self".to_string(),
|
||||
type_: "application/activity+json".to_string(),
|
||||
href: user_url,
|
||||
}],
|
||||
};
|
||||
|
||||
Ok(Json(response))
|
||||
} else {
|
||||
Err((
|
||||
axum::http::StatusCode::BAD_REQUEST,
|
||||
"Invalid resource format",
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn create_well_known_router() -> axum::Router<AppState> {
|
||||
axum::Router::new().route("/webfinger", axum::routing::get(webfinger))
|
||||
}
|
Reference in New Issue
Block a user