mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-14 08:23:59 +00:00
77a2a5eb01
Merge branch 'main' into more-upgrade-apub-3 Update activitystreams library to latest version Remove remaining usages of old activitystreams library Migrate community inbox and user inbox Migrate private message Migrate post Migrate community activities Migrate extensions to new activitystreams library Co-authored-by: dessalines <dessalines@noreply.yerbamate.dev> Co-authored-by: Felix Ableitner <me@nutomic.com> Reviewed-on: https://yerbamate.dev/LemmyNet/lemmy/pulls/71
132 lines
3.5 KiB
Rust
132 lines
3.5 KiB
Rust
use crate::{
|
|
apub::{
|
|
extensions::signatures::verify,
|
|
fetcher::{get_or_fetch_and_upsert_remote_community, get_or_fetch_and_upsert_remote_user},
|
|
insert_activity, ActorType,
|
|
},
|
|
blocking,
|
|
routes::{ChatServerParam, DbPoolParam},
|
|
LemmyError,
|
|
};
|
|
use activitystreams_new::{
|
|
activity::{Follow, Undo},
|
|
prelude::*,
|
|
};
|
|
use actix_web::{client::Client, web, HttpRequest, HttpResponse};
|
|
use lemmy_db::{
|
|
community::{Community, CommunityFollower, CommunityFollowerForm},
|
|
user::User_,
|
|
Followable,
|
|
};
|
|
use log::debug;
|
|
use serde::Deserialize;
|
|
use std::fmt::Debug;
|
|
|
|
#[serde(untagged)]
|
|
#[derive(Deserialize, Debug)]
|
|
pub enum CommunityAcceptedObjects {
|
|
Follow(Follow),
|
|
Undo(Undo),
|
|
}
|
|
|
|
impl CommunityAcceptedObjects {
|
|
fn follow(&self) -> Result<Follow, LemmyError> {
|
|
match self {
|
|
CommunityAcceptedObjects::Follow(f) => Ok(f.to_owned()),
|
|
CommunityAcceptedObjects::Undo(u) => {
|
|
Ok(Follow::from_any_base(u.object().as_one().unwrap().to_owned())?.unwrap())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Handler for all incoming activities to community inboxes.
|
|
pub async fn community_inbox(
|
|
request: HttpRequest,
|
|
input: web::Json<CommunityAcceptedObjects>,
|
|
path: web::Path<String>,
|
|
db: DbPoolParam,
|
|
client: web::Data<Client>,
|
|
_chat_server: ChatServerParam,
|
|
) -> Result<HttpResponse, LemmyError> {
|
|
let input = input.into_inner();
|
|
|
|
let path = path.into_inner();
|
|
let community = blocking(&db, move |conn| Community::read_from_name(&conn, &path)).await??;
|
|
|
|
if !community.local {
|
|
return Err(
|
|
format_err!(
|
|
"Received activity is addressed to remote community {}",
|
|
&community.actor_id
|
|
)
|
|
.into(),
|
|
);
|
|
}
|
|
debug!(
|
|
"Community {} received activity {:?}",
|
|
&community.name, &input
|
|
);
|
|
let follow = input.follow()?;
|
|
let user_uri = follow.actor()?.as_single_xsd_any_uri().unwrap();
|
|
let community_uri = follow.object().as_single_xsd_any_uri().unwrap();
|
|
|
|
let user = get_or_fetch_and_upsert_remote_user(&user_uri, &client, &db).await?;
|
|
let community = get_or_fetch_and_upsert_remote_community(community_uri, &client, &db).await?;
|
|
|
|
verify(&request, &user)?;
|
|
|
|
match input {
|
|
CommunityAcceptedObjects::Follow(f) => handle_follow(f, user, community, &client, db).await,
|
|
CommunityAcceptedObjects::Undo(u) => handle_undo_follow(u, user, community, db).await,
|
|
}
|
|
}
|
|
|
|
/// Handle a follow request from a remote user, adding it to the local database and returning an
|
|
/// Accept activity.
|
|
async fn handle_follow(
|
|
follow: Follow,
|
|
user: User_,
|
|
community: Community,
|
|
client: &Client,
|
|
db: DbPoolParam,
|
|
) -> Result<HttpResponse, LemmyError> {
|
|
insert_activity(user.id, follow.clone(), false, &db).await?;
|
|
|
|
let community_follower_form = CommunityFollowerForm {
|
|
community_id: community.id,
|
|
user_id: user.id,
|
|
};
|
|
|
|
// This will fail if they're already a follower, but ignore the error.
|
|
blocking(&db, move |conn| {
|
|
CommunityFollower::follow(&conn, &community_follower_form).ok()
|
|
})
|
|
.await?;
|
|
|
|
community.send_accept_follow(follow, &client, &db).await?;
|
|
|
|
Ok(HttpResponse::Ok().finish())
|
|
}
|
|
|
|
async fn handle_undo_follow(
|
|
undo: Undo,
|
|
user: User_,
|
|
community: Community,
|
|
db: DbPoolParam,
|
|
) -> Result<HttpResponse, LemmyError> {
|
|
insert_activity(user.id, undo, false, &db).await?;
|
|
|
|
let community_follower_form = CommunityFollowerForm {
|
|
community_id: community.id,
|
|
user_id: user.id,
|
|
};
|
|
|
|
// This will fail if they aren't a follower, but ignore the error.
|
|
blocking(&db, move |conn| {
|
|
CommunityFollower::unfollow(&conn, &community_follower_form).ok()
|
|
})
|
|
.await?;
|
|
|
|
Ok(HttpResponse::Ok().finish())
|
|
}
|