Add SendActivity trait so that api crates compile in parallel with lemmy_apub

This commit is contained in:
Felix Ableitner 2022-11-28 15:29:33 +01:00
parent 201fa97769
commit c6c52ab9cc
180 changed files with 2105 additions and 1398 deletions

4
Cargo.lock generated
View file

@ -2034,7 +2034,6 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
name = "lemmy_api"
version = "0.16.5"
dependencies = [
"activitypub_federation",
"actix-web",
"anyhow",
"async-trait",
@ -2044,7 +2043,6 @@ dependencies = [
"chrono",
"diesel",
"lemmy_api_common",
"lemmy_apub",
"lemmy_db_schema",
"lemmy_db_views",
"lemmy_db_views_actor",
@ -2103,7 +2101,6 @@ dependencies = [
"async-trait",
"bcrypt",
"lemmy_api_common",
"lemmy_apub",
"lemmy_db_schema",
"lemmy_db_views",
"lemmy_db_views_actor",
@ -2274,6 +2271,7 @@ dependencies = [
"reqwest-retry",
"reqwest-tracing",
"serde",
"serde_json",
"tracing",
"tracing-actix-web",
"tracing-error",

View file

@ -135,6 +135,7 @@ clokwerk = { workspace = true }
doku = { workspace = true }
parking_lot = { workspace = true }
reqwest-retry = { workspace = true }
serde_json = { workspace = true }
tracing-opentelemetry = { workspace = true, optional = true }
opentelemetry = { workspace = true, optional = true }
console-subscriber = { version = "0.1.8", optional = true }

View file

@ -187,12 +187,15 @@ test("Admin actions in remote community are not federated to origin", async () =
let gammaCommunity = (
await resolveCommunity(gamma, communityRes.community.actor_id)
).community.unwrap();
let gammaFollow = await followCommunity(
await followCommunity(
gamma,
true,
gammaCommunity.community.id
);
expect(gammaFollow.community_view.subscribed).toBe("Subscribed");
gammaCommunity = (
await resolveCommunity(gamma, communityRes.community.actor_id)
).community.unwrap();
expect(gammaCommunity.subscribed).toBe("Subscribed");
let gammaPost = (await createPost(gamma, gammaCommunity.community.id))
.post_view;
expect(gammaPost.post.id).toBeDefined();

View file

@ -20,12 +20,13 @@ afterAll(async () => {
test("Follow federated community", async () => {
let betaCommunity = (await resolveBetaCommunity(alpha)).community.unwrap();
let follow = await followCommunity(alpha, true, betaCommunity.community.id);
await followCommunity(alpha, true, betaCommunity.community.id);
betaCommunity = (await resolveBetaCommunity(alpha)).community.unwrap();
// Make sure the follow response went through
expect(follow.community_view.community.local).toBe(false);
expect(follow.community_view.community.name).toBe("main");
expect(follow.community_view.subscribed).toBe(SubscribedType.Subscribed);
expect(betaCommunity.community.local).toBe(false);
expect(betaCommunity.community.name).toBe("main");
expect(betaCommunity.subscribed).toBe(SubscribedType.Subscribed);
// Check it from local
let site = await getSite(alpha);

View file

@ -14,14 +14,12 @@ path = "src/lib.rs"
doctest = false
[dependencies]
lemmy_apub = { workspace = true }
lemmy_utils = { workspace = true }
lemmy_db_schema = { workspace = true, features = ["full"] }
lemmy_db_views = { workspace = true, features = ["full"] }
lemmy_db_views_moderator = { workspace = true, features = ["full"] }
lemmy_db_views_actor = { workspace = true, features = ["full"] }
lemmy_api_common = { workspace = true, features = ["full"] }
activitypub_federation = { workspace = true }
diesel = { workspace = true }
bcrypt = { workspace = true }
chrono = { workspace = true }

View file

@ -2,16 +2,9 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, CreateCommentLike},
context::LemmyContext,
utils::{check_community_ban, check_downvotes_enabled, get_local_user_view_from_jwt},
websocket::{send::send_comment_ws_message, UserOperation},
LemmyContext,
};
use lemmy_apub::{
fetcher::post_or_comment::PostOrComment,
protocol::activities::voting::{
undo_vote::UndoVote,
vote::{Vote, VoteType},
},
};
use lemmy_db_schema::{
newtypes::LocalUserId,
@ -24,7 +17,6 @@ use lemmy_db_schema::{
};
use lemmy_db_views::structs::{CommentView, LocalUserView};
use lemmy_utils::{error::LemmyError, ConnectionId};
use std::convert::TryInto;
#[async_trait::async_trait(?Send)]
impl Perform for CreateCommentLike {
@ -78,33 +70,12 @@ impl Perform for CreateCommentLike {
CommentLike::remove(context.pool(), person_id, comment_id).await?;
// Only add the like if the score isnt 0
let comment = orig_comment.comment;
let object = PostOrComment::Comment(Box::new(comment.into()));
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
if do_add {
let like_form2 = like_form.clone();
CommentLike::like(context.pool(), &like_form2)
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
Vote::send(
&object,
&local_user_view.person.clone().into(),
orig_comment.community.id,
like_form.score.try_into()?,
context,
)
.await?;
} else {
// API doesn't distinguish between Undo/Like and Undo/Dislike
UndoVote::send(
&object,
&local_user_view.person.clone().into(),
orig_comment.community.id,
VoteType::Like,
context,
)
.await?;
}
send_comment_ws_message(

View file

@ -2,8 +2,8 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, SaveComment},
context::LemmyContext,
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::{
source::comment::{CommentSaved, CommentSavedForm},

View file

@ -1,13 +1,11 @@
use crate::{check_report_reason, Perform};
use activitypub_federation::core::object_id::ObjectId;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentReportResponse, CreateCommentReport},
context::LemmyContext,
utils::{check_community_ban, get_local_user_view_from_jwt},
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_apub::protocol::activities::community::report::Report;
use lemmy_db_schema::{
source::{
comment_report::{CommentReport, CommentReportForm},
@ -67,15 +65,6 @@ impl Perform for CreateCommentReport {
websocket_id,
});
Report::send(
ObjectId::new(comment_view.comment.ap_id),
&local_user_view.person.into(),
ObjectId::new(comment_view.community.actor_id),
reason.to_string(),
context,
)
.await?;
Ok(res)
}
}

View file

@ -2,8 +2,8 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{ListCommentReports, ListCommentReportsResponse},
context::LemmyContext,
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views::comment_report_view::CommentReportQuery;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -2,9 +2,9 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentReportResponse, ResolveCommentReport},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, is_mod_or_admin},
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{source::comment_report::CommentReport, traits::Reportable};
use lemmy_db_views::structs::CommentReportView;

View file

@ -2,19 +2,14 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, is_mod_or_admin},
websocket::{messages::SendCommunityRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_apub::{
objects::{community::ApubCommunity, person::ApubPerson},
protocol::activities::community::{add_mod::AddMod, remove_mod::RemoveMod},
};
use lemmy_db_schema::{
source::{
community::{Community, CommunityModerator, CommunityModeratorForm},
moderator::{ModAddCommunity, ModAddCommunityForm},
person::Person,
},
traits::{Crud, Joinable},
};
@ -69,28 +64,6 @@ impl Perform for AddModToCommunity {
ModAddCommunity::create(context.pool(), &form).await?;
// Send to federated instances
let updated_mod_id = data.person_id;
let updated_mod: ApubPerson = Person::read(context.pool(), updated_mod_id).await?.into();
let community: ApubCommunity = community.into();
if data.added {
AddMod::send(
&community,
&updated_mod,
&local_user_view.person.into(),
context,
)
.await?;
} else {
RemoveMod::send(
&community,
&updated_mod,
&local_user_view.person.into(),
context,
)
.await?;
}
// Note: in case a remote mod is added, this returns the old moderators list, it will only get
// updated once we receive an activity from the community (like `Announce/Add/Moderator`)
let community_id = data.community_id;

View file

@ -2,26 +2,19 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, is_mod_or_admin, remove_user_data_in_community},
websocket::{messages::SendCommunityRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_apub::{
activities::block::SiteOrCommunity,
objects::{community::ApubCommunity, person::ApubPerson},
protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
};
use lemmy_db_schema::{
source::{
community::{
Community,
CommunityFollower,
CommunityFollowerForm,
CommunityPersonBan,
CommunityPersonBanForm,
},
moderator::{ModBanFromCommunity, ModBanFromCommunityForm},
person::Person,
},
traits::{Bannable, Crud, Followable},
};
@ -56,9 +49,6 @@ impl Perform for BanFromCommunity {
expires: Some(expires),
};
let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
let banned_person: ApubPerson = Person::read(context.pool(), banned_person_id).await?.into();
if data.ban {
CommunityPersonBan::ban(context.pool(), &community_user_ban_form)
.await
@ -74,29 +64,10 @@ impl Perform for BanFromCommunity {
CommunityFollower::unfollow(context.pool(), &community_follower_form)
.await
.ok();
BlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
remove_data,
data.reason.clone(),
expires,
context,
)
.await?;
} else {
CommunityPersonBan::unban(context.pool(), &community_user_ban_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "community_user_already_banned"))?;
UndoBlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
data.reason.clone(),
context,
)
.await?;
}
// Remove/Restore their data if that's desired

View file

@ -2,16 +2,15 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{BlockCommunity, BlockCommunityResponse},
context::LemmyContext,
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_apub::protocol::activities::following::undo_follow::UndoFollow;
use lemmy_db_schema::{
source::{
community::{Community, CommunityFollower, CommunityFollowerForm},
community::{CommunityFollower, CommunityFollowerForm},
community_block::{CommunityBlock, CommunityBlockForm},
},
traits::{Blockable, Crud, Followable},
traits::{Blockable, Followable},
};
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::{error::LemmyError, ConnectionId};
@ -52,8 +51,6 @@ impl Perform for BlockCommunity {
CommunityFollower::unfollow(context.pool(), &community_follower_form)
.await
.ok();
let community = Community::read(context.pool(), community_id).await?;
UndoFollow::send(&local_user_view.person.into(), &community.into(), context).await?;
} else {
CommunityBlock::unblock(context.pool(), &community_block_form)
.await

View file

@ -2,15 +2,8 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, FollowCommunity},
context::LemmyContext,
utils::{check_community_ban, check_community_deleted_or_removed, get_local_user_view_from_jwt},
LemmyContext,
};
use lemmy_apub::{
objects::community::ApubCommunity,
protocol::activities::following::{
follow::Follow as FollowCommunityApub,
undo_follow::UndoFollow,
},
};
use lemmy_db_schema::{
source::community::{Community, CommunityFollower, CommunityFollowerForm},
@ -34,33 +27,22 @@ impl Perform for FollowCommunity {
get_local_user_view_from_jwt(&data.auth, context.pool(), context.secret()).await?;
let community_id = data.community_id;
let community: ApubCommunity = Community::read(context.pool(), community_id).await?.into();
let community = Community::read(context.pool(), community_id).await?;
let community_follower_form = CommunityFollowerForm {
community_id: data.community_id,
person_id: local_user_view.person.id,
pending: false,
};
if community.local {
if data.follow {
check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
check_community_deleted_or_removed(community_id, context.pool()).await?;
if community.local && data.follow {
check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
check_community_deleted_or_removed(community_id, context.pool()).await?;
CommunityFollower::follow(context.pool(), &community_follower_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
} else {
CommunityFollower::unfollow(context.pool(), &community_follower_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
}
} else if data.follow {
// Dont actually add to the community followers here, because you need
// to wait for the accept
FollowCommunityApub::send(&local_user_view.person.clone().into(), &community, context)
.await?;
} else {
UndoFollow::send(&local_user_view.person.clone().into(), &community, context).await?;
CommunityFollower::follow(context.pool(), &community_follower_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;
}
if !data.follow {
CommunityFollower::unfollow(context.pool(), &community_follower_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "community_follower_already_exists"))?;

View file

@ -2,11 +2,10 @@ use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, HideCommunity},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, is_admin},
websocket::{send::send_community_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
use lemmy_db_schema::{
source::{
community::{Community, CommunityUpdateForm},
@ -45,19 +44,12 @@ impl Perform for HideCommunity {
};
let community_id = data.community_id;
let updated_community = Community::update(context.pool(), community_id, &community_form)
Community::update(context.pool(), community_id, &community_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community_hidden_status"))?;
ModHideCommunity::create(context.pool(), &mod_hide_community_form).await?;
UpdateCommunity::send(
updated_community.into(),
&local_user_view.person.into(),
context,
)
.await?;
let op = UserOperationCrud::EditCommunity;
send_community_ws_message(data.community_id, op, websocket_id, None, context).await
}

View file

@ -3,8 +3,8 @@ use actix_web::web::Data;
use anyhow::Context;
use lemmy_api_common::{
community::{GetCommunityResponse, TransferCommunity},
context::LemmyContext,
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,81 +1,8 @@
use actix_web::{web, web::Data};
use actix_web::web::Data;
use captcha::Captcha;
use lemmy_api_common::{
comment::{
CreateCommentLike,
CreateCommentReport,
ListCommentReports,
ResolveCommentReport,
SaveComment,
},
community::{
AddModToCommunity,
BanFromCommunity,
BlockCommunity,
FollowCommunity,
TransferCommunity,
},
person::{
AddAdmin,
BanPerson,
BlockPerson,
ChangePassword,
GetBannedPersons,
GetCaptcha,
GetPersonMentions,
GetReplies,
GetReportCount,
GetUnreadCount,
Login,
MarkAllAsRead,
MarkCommentReplyAsRead,
MarkPersonMentionAsRead,
PasswordChangeAfterReset,
PasswordReset,
SaveUserSettings,
VerifyEmail,
},
post::{
CreatePostLike,
CreatePostReport,
GetSiteMetadata,
ListPostReports,
LockPost,
MarkPostAsRead,
ResolvePostReport,
SavePost,
StickyPost,
},
private_message::{
CreatePrivateMessageReport,
ListPrivateMessageReports,
MarkPrivateMessageAsRead,
ResolvePrivateMessageReport,
},
site::{
ApproveRegistrationApplication,
GetModlog,
GetUnreadRegistrationApplicationCount,
LeaveAdmin,
ListRegistrationApplications,
PurgeComment,
PurgeCommunity,
PurgePerson,
PurgePost,
ResolveObject,
Search,
},
utils::local_site_to_slur_regex,
websocket::{
serialize_websocket_message,
structs::{CommunityJoin, ModJoin, PostJoin, UserJoin},
UserOperation,
},
LemmyContext,
};
use lemmy_api_common::{context::LemmyContext, utils::local_site_to_slur_regex};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_utils::{error::LemmyError, utils::check_slurs, ConnectionId};
use serde::Deserialize;
mod comment;
mod comment_report;
@ -99,182 +26,6 @@ pub trait Perform {
) -> Result<Self::Response, LemmyError>;
}
pub async fn match_websocket_operation(
context: LemmyContext,
id: ConnectionId,
op: UserOperation,
data: &str,
) -> Result<String, LemmyError> {
match op {
// User ops
UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await,
UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await,
UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
UserOperation::GetUnreadRegistrationApplicationCount => {
do_websocket_operation::<GetUnreadRegistrationApplicationCount>(context, id, op, data).await
}
UserOperation::ListRegistrationApplications => {
do_websocket_operation::<ListRegistrationApplications>(context, id, op, data).await
}
UserOperation::ApproveRegistrationApplication => {
do_websocket_operation::<ApproveRegistrationApplication>(context, id, op, data).await
}
UserOperation::BanPerson => do_websocket_operation::<BanPerson>(context, id, op, data).await,
UserOperation::GetBannedPersons => {
do_websocket_operation::<GetBannedPersons>(context, id, op, data).await
}
UserOperation::BlockPerson => {
do_websocket_operation::<BlockPerson>(context, id, op, data).await
}
UserOperation::GetPersonMentions => {
do_websocket_operation::<GetPersonMentions>(context, id, op, data).await
}
UserOperation::MarkPersonMentionAsRead => {
do_websocket_operation::<MarkPersonMentionAsRead>(context, id, op, data).await
}
UserOperation::MarkCommentReplyAsRead => {
do_websocket_operation::<MarkCommentReplyAsRead>(context, id, op, data).await
}
UserOperation::MarkAllAsRead => {
do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await
}
UserOperation::PasswordReset => {
do_websocket_operation::<PasswordReset>(context, id, op, data).await
}
UserOperation::PasswordChange => {
do_websocket_operation::<PasswordChangeAfterReset>(context, id, op, data).await
}
UserOperation::UserJoin => do_websocket_operation::<UserJoin>(context, id, op, data).await,
UserOperation::PostJoin => do_websocket_operation::<PostJoin>(context, id, op, data).await,
UserOperation::CommunityJoin => {
do_websocket_operation::<CommunityJoin>(context, id, op, data).await
}
UserOperation::ModJoin => do_websocket_operation::<ModJoin>(context, id, op, data).await,
UserOperation::SaveUserSettings => {
do_websocket_operation::<SaveUserSettings>(context, id, op, data).await
}
UserOperation::ChangePassword => {
do_websocket_operation::<ChangePassword>(context, id, op, data).await
}
UserOperation::GetReportCount => {
do_websocket_operation::<GetReportCount>(context, id, op, data).await
}
UserOperation::GetUnreadCount => {
do_websocket_operation::<GetUnreadCount>(context, id, op, data).await
}
UserOperation::VerifyEmail => {
do_websocket_operation::<VerifyEmail>(context, id, op, data).await
}
// Private Message ops
UserOperation::MarkPrivateMessageAsRead => {
do_websocket_operation::<MarkPrivateMessageAsRead>(context, id, op, data).await
}
UserOperation::CreatePrivateMessageReport => {
do_websocket_operation::<CreatePrivateMessageReport>(context, id, op, data).await
}
UserOperation::ResolvePrivateMessageReport => {
do_websocket_operation::<ResolvePrivateMessageReport>(context, id, op, data).await
}
UserOperation::ListPrivateMessageReports => {
do_websocket_operation::<ListPrivateMessageReports>(context, id, op, data).await
}
// Site ops
UserOperation::GetModlog => do_websocket_operation::<GetModlog>(context, id, op, data).await,
UserOperation::PurgePerson => {
do_websocket_operation::<PurgePerson>(context, id, op, data).await
}
UserOperation::PurgeCommunity => {
do_websocket_operation::<PurgeCommunity>(context, id, op, data).await
}
UserOperation::PurgePost => do_websocket_operation::<PurgePost>(context, id, op, data).await,
UserOperation::PurgeComment => {
do_websocket_operation::<PurgeComment>(context, id, op, data).await
}
UserOperation::Search => do_websocket_operation::<Search>(context, id, op, data).await,
UserOperation::ResolveObject => {
do_websocket_operation::<ResolveObject>(context, id, op, data).await
}
UserOperation::TransferCommunity => {
do_websocket_operation::<TransferCommunity>(context, id, op, data).await
}
UserOperation::LeaveAdmin => do_websocket_operation::<LeaveAdmin>(context, id, op, data).await,
// Community ops
UserOperation::FollowCommunity => {
do_websocket_operation::<FollowCommunity>(context, id, op, data).await
}
UserOperation::BlockCommunity => {
do_websocket_operation::<BlockCommunity>(context, id, op, data).await
}
UserOperation::BanFromCommunity => {
do_websocket_operation::<BanFromCommunity>(context, id, op, data).await
}
UserOperation::AddModToCommunity => {
do_websocket_operation::<AddModToCommunity>(context, id, op, data).await
}
// Post ops
UserOperation::LockPost => do_websocket_operation::<LockPost>(context, id, op, data).await,
UserOperation::StickyPost => do_websocket_operation::<StickyPost>(context, id, op, data).await,
UserOperation::CreatePostLike => {
do_websocket_operation::<CreatePostLike>(context, id, op, data).await
}
UserOperation::MarkPostAsRead => {
do_websocket_operation::<MarkPostAsRead>(context, id, op, data).await
}
UserOperation::SavePost => do_websocket_operation::<SavePost>(context, id, op, data).await,
UserOperation::CreatePostReport => {
do_websocket_operation::<CreatePostReport>(context, id, op, data).await
}
UserOperation::ListPostReports => {
do_websocket_operation::<ListPostReports>(context, id, op, data).await
}
UserOperation::ResolvePostReport => {
do_websocket_operation::<ResolvePostReport>(context, id, op, data).await
}
UserOperation::GetSiteMetadata => {
do_websocket_operation::<GetSiteMetadata>(context, id, op, data).await
}
// Comment ops
UserOperation::SaveComment => {
do_websocket_operation::<SaveComment>(context, id, op, data).await
}
UserOperation::CreateCommentLike => {
do_websocket_operation::<CreateCommentLike>(context, id, op, data).await
}
UserOperation::CreateCommentReport => {
do_websocket_operation::<CreateCommentReport>(context, id, op, data).await
}
UserOperation::ListCommentReports => {
do_websocket_operation::<ListCommentReports>(context, id, op, data).await
}
UserOperation::ResolveCommentReport => {
do_websocket_operation::<ResolveCommentReport>(context, id, op, data).await
}
}
}
async fn do_websocket_operation<'a, 'b, Data>(
context: LemmyContext,
id: ConnectionId,
op: UserOperation,
data: &str,
) -> Result<String, LemmyError>
where
for<'de> Data: Deserialize<'de> + 'a,
Data: Perform,
{
let parsed_data: Data = serde_json::from_str(data)?;
let res = parsed_data
.perform(&web::Data::new(context), Some(id))
.await?;
serialize_websocket_message(&op, &res)
}
/// Converts the captcha to a base64 encoded wav audio file
pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> String {
let letters = captcha.as_wav();

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{AddAdmin, AddAdminResponse},
utils::{get_local_user_view_from_jwt, is_admin},
websocket::{messages::SendAllMessage, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,14 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{BanPerson, BanPersonResponse},
utils::{get_local_user_view_from_jwt, is_admin, remove_user_data},
websocket::{messages::SendAllMessage, UserOperation},
LemmyContext,
};
use lemmy_apub::{
activities::block::SiteOrCommunity,
protocol::activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
};
use lemmy_db_schema::{
source::{
@ -17,7 +13,6 @@ use lemmy_db_schema::{
},
traits::Crud,
};
use lemmy_db_views::structs::SiteView;
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{error::LemmyError, utils::naive_from_unix, ConnectionId};
@ -79,32 +74,6 @@ impl Perform for BanPerson {
let person_id = data.person_id;
let person_view = PersonViewSafe::read(context.pool(), person_id).await?;
let site = SiteOrCommunity::Site(SiteView::read_local(context.pool()).await?.site.into());
// if the action affects a local user, federate to other instances
if person.local {
if ban {
BlockUser::send(
&site,
&person.into(),
&local_user_view.person.into(),
remove_data,
data.reason.clone(),
expires,
context,
)
.await?;
} else {
UndoBlockUser::send(
&site,
&person.into(),
&local_user_view.person.into(),
data.reason.clone(),
context,
)
.await?;
}
}
let res = BanPersonResponse {
person_view,
banned: data.ban,

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{BlockPerson, BlockPersonResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::{
source::person_block::{PersonBlock, PersonBlockForm},

View file

@ -2,9 +2,9 @@ use crate::Perform;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{
context::LemmyContext,
person::{ChangePassword, LoginResponse},
utils::{get_local_user_view_from_jwt, password_length_check},
LemmyContext,
};
use lemmy_db_schema::source::local_user::LocalUser;
use lemmy_utils::{claims::Claims, error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{LoginResponse, PasswordChangeAfterReset},
utils::password_length_check,
LemmyContext,
};
use lemmy_db_schema::source::{
local_user::LocalUser,

View file

@ -3,9 +3,9 @@ use actix_web::web::Data;
use captcha::{gen, Difficulty};
use chrono::Duration;
use lemmy_api_common::{
context::LemmyContext,
person::{CaptchaResponse, GetCaptcha, GetCaptchaResponse},
websocket::messages::CaptchaItem,
LemmyContext,
};
use lemmy_db_schema::{source::local_site::LocalSite, utils::naive_now};
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{BannedPersonsResponse, GetBannedPersons},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_views_actor::structs::PersonViewSafe;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -2,9 +2,9 @@ use crate::Perform;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{
context::LemmyContext,
person::{Login, LoginResponse},
utils::{check_registration_application, check_user_valid},
LemmyContext,
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::structs::LocalUserView;

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{GetPersonMentions, GetPersonMentionsResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views_actor::person_mention_view::PersonMentionQuery;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{GetReplies, GetRepliesResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views_actor::comment_reply_view::CommentReplyQuery;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{GetRepliesResponse, MarkAllAsRead},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::source::{
comment_reply::CommentReply,

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{MarkPersonMentionAsRead, PersonMentionResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::{
source::person_mention::{PersonMention, PersonMentionUpdateForm},

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{CommentReplyResponse, MarkCommentReplyAsRead},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::{
source::comment_reply::{CommentReply, CommentReplyUpdateForm},

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{GetUnreadCount, GetUnreadCountResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views::structs::PrivateMessageView;
use lemmy_db_views_actor::structs::{CommentReplyView, PersonMentionView};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{GetReportCount, GetReportCountResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views::structs::{CommentReportView, PostReportView, PrivateMessageReportView};
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{PasswordReset, PasswordResetResponse},
utils::send_password_reset_email,
LemmyContext,
};
use lemmy_db_views::structs::LocalUserView;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{LoginResponse, SaveUserSettings},
utils::{get_local_user_view_from_jwt, send_verification_email},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
person::{VerifyEmail, VerifyEmailResponse},
utils::send_email_verification_success,
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{GetSiteMetadata, GetSiteMetadataResponse},
request::fetch_site_metadata,
LemmyContext,
};
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,6 +1,7 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{CreatePostLike, PostResponse},
utils::{
check_community_ban,
@ -10,15 +11,6 @@ use lemmy_api_common::{
mark_post_as_read,
},
websocket::{send::send_post_ws_message, UserOperation},
LemmyContext,
};
use lemmy_apub::{
fetcher::post_or_comment::PostOrComment,
objects::post::ApubPost,
protocol::activities::voting::{
undo_vote::UndoVote,
vote::{Vote, VoteType},
},
};
use lemmy_db_schema::{
source::{
@ -49,7 +41,7 @@ impl Perform for CreatePostLike {
// Check for a community ban
let post_id = data.post_id;
let post: ApubPost = Post::read(context.pool(), post_id).await?.into();
let post = Post::read(context.pool(), post_id).await?;
check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
check_community_deleted_or_removed(post.community_id, context.pool()).await?;
@ -65,9 +57,6 @@ impl Perform for CreatePostLike {
PostLike::remove(context.pool(), person_id, post_id).await?;
let community_id = post.community_id;
let object = PostOrComment::Post(Box::new(post));
// Only add the like if the score isnt 0
let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
if do_add {
@ -75,25 +64,6 @@ impl Perform for CreatePostLike {
PostLike::like(context.pool(), &like_form2)
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_like_post"))?;
Vote::send(
&object,
&local_user_view.person.clone().into(),
community_id,
like_form.score.try_into()?,
context,
)
.await?;
} else {
// API doesn't distinguish between Undo/Like and Undo/Dislike
UndoVote::send(
&object,
&local_user_view.person.clone().into(),
community_id,
VoteType::Like,
context,
)
.await?;
}
// Mark the post as read

View file

@ -1,6 +1,7 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{LockPost, PostResponse},
utils::{
check_community_ban,
@ -9,11 +10,6 @@ use lemmy_api_common::{
is_mod_or_admin,
},
websocket::{send::send_post_ws_message, UserOperation},
LemmyContext,
};
use lemmy_apub::{
objects::post::ApubPost,
protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
};
use lemmy_db_schema::{
source::{
@ -60,13 +56,12 @@ impl Perform for LockPost {
// Update the post
let post_id = data.post_id;
let locked = data.locked;
let updated_post: ApubPost = Post::update(
Post::update(
context.pool(),
post_id,
&PostUpdateForm::builder().locked(Some(locked)).build(),
)
.await?
.into();
.await?;
// Mod tables
let form = ModLockPostForm {
@ -76,15 +71,6 @@ impl Perform for LockPost {
};
ModLockPost::create(context.pool(), &form).await?;
// apub updates
CreateOrUpdatePage::send(
updated_post,
&local_user_view.person.clone().into(),
CreateOrUpdateType::Update,
context,
)
.await?;
send_post_ws_message(
data.post_id,
UserOperation::LockPost,

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{MarkPostAsRead, PostResponse},
utils::{get_local_user_view_from_jwt, mark_post_as_read, mark_post_as_unread},
LemmyContext,
};
use lemmy_db_views::structs::PostView;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{PostResponse, SavePost},
utils::{get_local_user_view_from_jwt, mark_post_as_read},
LemmyContext,
};
use lemmy_db_schema::{
source::post::{PostSaved, PostSavedForm},

View file

@ -1,6 +1,7 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{PostResponse, StickyPost},
utils::{
check_community_ban,
@ -9,11 +10,6 @@ use lemmy_api_common::{
is_mod_or_admin,
},
websocket::{send::send_post_ws_message, UserOperation},
LemmyContext,
};
use lemmy_apub::{
objects::post::ApubPost,
protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
};
use lemmy_db_schema::{
source::{
@ -60,13 +56,12 @@ impl Perform for StickyPost {
// Update the post
let post_id = data.post_id;
let stickied = data.stickied;
let updated_post: ApubPost = Post::update(
Post::update(
context.pool(),
post_id,
&PostUpdateForm::builder().stickied(Some(stickied)).build(),
)
.await?
.into();
.await?;
// Mod tables
let form = ModStickyPostForm {
@ -77,16 +72,6 @@ impl Perform for StickyPost {
ModStickyPost::create(context.pool(), &form).await?;
// Apub updates
// TODO stickied should pry work like locked for ease of use
CreateOrUpdatePage::send(
updated_post,
&local_user_view.person.clone().into(),
CreateOrUpdateType::Update,
context,
)
.await?;
send_post_ws_message(
data.post_id,
UserOperation::StickyPost,

View file

@ -1,13 +1,11 @@
use crate::{check_report_reason, Perform};
use activitypub_federation::core::object_id::ObjectId;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{CreatePostReport, PostReportResponse},
utils::{check_community_ban, get_local_user_view_from_jwt},
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_apub::protocol::activities::community::report::Report;
use lemmy_db_schema::{
source::{
local_site::LocalSite,
@ -67,15 +65,6 @@ impl Perform for CreatePostReport {
websocket_id,
});
Report::send(
ObjectId::new(post_view.post.ap_id),
&local_user_view.person.into(),
ObjectId::new(post_view.community.actor_id),
reason.to_string(),
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{ListPostReports, ListPostReportsResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_views::post_report_view::PostReportQuery;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{PostReportResponse, ResolvePostReport},
utils::{get_local_user_view_from_jwt, is_mod_or_admin},
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{source::post_report::PostReport, traits::Reportable};
use lemmy_db_views::structs::PostReportView;

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{MarkPrivateMessageAsRead, PrivateMessageResponse},
utils::get_local_user_view_from_jwt,
websocket::{send::send_pm_ws_message, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{
source::private_message::{PrivateMessage, PrivateMessageUpdateForm},

View file

@ -1,10 +1,10 @@
use crate::{check_report_reason, Perform};
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{CreatePrivateMessageReport, PrivateMessageReportResponse},
utils::get_local_user_view_from_jwt,
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{
newtypes::CommunityId,

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{ListPrivateMessageReports, ListPrivateMessageReportsResponse},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_views::private_message_report_view::PrivateMessageReportQuery;
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{PrivateMessageReportResponse, ResolvePrivateMessageReport},
utils::{get_local_user_view_from_jwt, is_admin},
websocket::{messages::SendModRoomMessage, UserOperation},
LemmyContext,
};
use lemmy_db_schema::{
newtypes::CommunityId,

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{GetSiteResponse, LeaveAdmin},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -2,5 +2,3 @@ mod leave_admin;
mod mod_log;
mod purge;
mod registration_applications;
mod resolve_object;
mod search;

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{GetModlog, GetModlogResponse},
utils::{check_private_instance, get_local_user_view_from_jwt_opt, is_admin, is_mod_or_admin},
LemmyContext,
};
use lemmy_db_schema::{
newtypes::{CommunityId, PersonId},

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{PurgeComment, PurgeItemResponse},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
request::purge_image_from_pictrs,
site::{PurgeCommunity, PurgeItemResponse},
utils::{get_local_user_view_from_jwt, is_admin, purge_image_posts_for_community},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
request::purge_image_from_pictrs,
site::{PurgeItemResponse, PurgePerson},
utils::{get_local_user_view_from_jwt, is_admin, purge_image_posts_for_person},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,10 +1,10 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
request::purge_image_from_pictrs,
site::{PurgeItemResponse, PurgePost},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{ApproveRegistrationApplication, RegistrationApplicationResponse},
utils::{get_local_user_view_from_jwt, is_admin, send_application_approved_email},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{ListRegistrationApplications, ListRegistrationApplicationsResponse},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::registration_application_view::RegistrationApplicationQuery;

View file

@ -1,9 +1,9 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{GetUnreadRegistrationApplicationCount, GetUnreadRegistrationApplicationCountResponse},
utils::{get_local_user_view_from_jwt, is_admin},
LemmyContext,
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::structs::RegistrationApplicationView;

View file

@ -1,6 +1,7 @@
use crate::Perform;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
utils::get_local_user_view_from_jwt,
websocket::{
messages::{JoinCommunityRoom, JoinModRoom, JoinPostRoom, JoinUserRoom},
@ -15,7 +16,6 @@ use lemmy_api_common::{
UserJoinResponse,
},
},
LemmyContext,
};
use lemmy_utils::{error::LemmyError, ConnectionId};

View file

@ -0,0 +1,68 @@
use crate::websocket::chat_server::ChatServer;
use actix::Addr;
use lemmy_db_schema::{source::secret::Secret, utils::DbPool};
use lemmy_utils::{
rate_limit::RateLimitCell,
settings::{structs::Settings, SETTINGS},
};
use reqwest_middleware::ClientWithMiddleware;
pub struct LemmyContext {
pool: DbPool,
chat_server: Addr<ChatServer>,
client: ClientWithMiddleware,
settings: Settings,
secret: Secret,
rate_limit_cell: RateLimitCell,
}
impl LemmyContext {
pub fn create(
pool: DbPool,
chat_server: Addr<ChatServer>,
client: ClientWithMiddleware,
settings: Settings,
secret: Secret,
rate_limit_cell: RateLimitCell,
) -> LemmyContext {
LemmyContext {
pool,
chat_server,
client,
settings,
secret,
rate_limit_cell,
}
}
pub fn pool(&self) -> &DbPool {
&self.pool
}
pub fn chat_server(&self) -> &Addr<ChatServer> {
&self.chat_server
}
pub fn client(&self) -> &ClientWithMiddleware {
&self.client
}
pub fn settings(&self) -> &'static Settings {
&SETTINGS
}
pub fn secret(&self) -> &Secret {
&self.secret
}
pub fn settings_updated_channel(&self) -> &RateLimitCell {
&self.rate_limit_cell
}
}
impl Clone for LemmyContext {
fn clone(&self) -> Self {
LemmyContext {
pool: self.pool.clone(),
chat_server: self.chat_server.clone(),
client: self.client.clone(),
settings: self.settings.clone(),
secret: self.secret.clone(),
rate_limit_cell: self.rate_limit_cell.clone(),
}
}
}

View file

@ -1,5 +1,7 @@
pub mod comment;
pub mod community;
#[cfg(feature = "full")]
pub mod context;
pub mod person;
pub mod post;
pub mod private_message;
@ -9,6 +11,7 @@ pub mod sensitive;
pub mod site;
#[cfg(feature = "full")]
pub mod utils;
#[cfg(feature = "full")]
pub mod websocket;
#[macro_use]
@ -17,138 +20,3 @@ pub extern crate lemmy_db_schema;
pub extern crate lemmy_db_views;
pub extern crate lemmy_db_views_actor;
pub extern crate lemmy_db_views_moderator;
use crate::websocket::chat_server::ChatServer;
use actix::Addr;
use anyhow::Context;
use lemmy_db_schema::{newtypes::DbUrl, source::secret::Secret, utils::DbPool};
use lemmy_utils::{
error::LemmyError,
location_info,
rate_limit::RateLimitCell,
settings::{structs::Settings, SETTINGS},
};
use reqwest_middleware::ClientWithMiddleware;
use url::{ParseError, Url};
pub struct LemmyContext {
pool: DbPool,
chat_server: Addr<ChatServer>,
client: ClientWithMiddleware,
settings: Settings,
secret: Secret,
rate_limit_cell: RateLimitCell,
}
impl LemmyContext {
pub fn create(
pool: DbPool,
chat_server: Addr<ChatServer>,
client: ClientWithMiddleware,
settings: Settings,
secret: Secret,
settings_updated_channel: RateLimitCell,
) -> LemmyContext {
LemmyContext {
pool,
chat_server,
client,
settings,
secret,
rate_limit_cell: settings_updated_channel,
}
}
pub fn pool(&self) -> &DbPool {
&self.pool
}
pub fn chat_server(&self) -> &Addr<ChatServer> {
&self.chat_server
}
pub fn client(&self) -> &ClientWithMiddleware {
&self.client
}
pub fn settings(&self) -> &'static Settings {
&SETTINGS
}
pub fn secret(&self) -> &Secret {
&self.secret
}
pub fn settings_updated_channel(&self) -> &RateLimitCell {
&self.rate_limit_cell
}
}
impl Clone for LemmyContext {
fn clone(&self) -> Self {
LemmyContext {
pool: self.pool.clone(),
chat_server: self.chat_server.clone(),
client: self.client.clone(),
settings: self.settings.clone(),
secret: self.secret.clone(),
rate_limit_cell: self.rate_limit_cell.clone(),
}
}
}
pub enum EndpointType {
Community,
Person,
Post,
Comment,
PrivateMessage,
}
/// Generates an apub endpoint for a given domain, IE xyz.tld
pub fn generate_local_apub_endpoint(
endpoint_type: EndpointType,
name: &str,
domain: &str,
) -> Result<DbUrl, ParseError> {
let point = match endpoint_type {
EndpointType::Community => "c",
EndpointType::Person => "u",
EndpointType::Post => "post",
EndpointType::Comment => "comment",
EndpointType::PrivateMessage => "private_message",
};
Ok(Url::parse(&format!("{}/{}/{}", domain, point, name))?.into())
}
pub fn generate_followers_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
}
pub fn generate_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
}
pub fn generate_site_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
let mut actor_id: Url = actor_id.clone().into();
actor_id.set_path("site_inbox");
Ok(actor_id.into())
}
pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError> {
let actor_id: Url = actor_id.clone().into();
let url = format!(
"{}://{}{}/inbox",
&actor_id.scheme(),
&actor_id.host_str().context(location_info!())?,
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
String::new()
},
);
Ok(Url::parse(&url)?.into())
}
pub fn generate_outbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/outbox", actor_id))?.into())
}
pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
}

View file

@ -268,7 +268,7 @@ pub struct GetUnreadCountResponse {
pub private_messages: i64,
}
#[derive(Serialize, Deserialize, Clone, Default)]
#[derive(Serialize, Deserialize, Clone, Default, Debug)]
pub struct VerifyEmail {
pub token: String,
}

View file

@ -1,8 +1,9 @@
use crate::{request::purge_image_from_pictrs, sensitive::Sensitive, site::FederatedInstances};
use anyhow::Context;
use chrono::NaiveDateTime;
use lemmy_db_schema::{
impls::person::is_banned,
newtypes::{CommunityId, LocalUserId, PersonId, PostId},
newtypes::{CommunityId, DbUrl, LocalUserId, PersonId, PostId},
source::{
comment::{Comment, CommentUpdateForm},
community::{Community, CommunityUpdateForm},
@ -34,6 +35,7 @@ use lemmy_utils::{
claims::Claims,
email::{send_email, translations::Lang},
error::LemmyError,
location_info,
rate_limit::RateLimitConfig,
settings::structs::Settings,
utils::{build_slur_regex, generate_random_string},
@ -43,6 +45,7 @@ use reqwest_middleware::ClientWithMiddleware;
use rosetta_i18n::{Language, LanguageId};
use std::str::FromStr;
use tracing::warn;
use url::{ParseError, Url};
#[tracing::instrument(skip_all)]
pub async fn is_mod_or_admin(
@ -743,3 +746,65 @@ mod tests {
assert!(honeypot_check(&Some("message".to_string())).is_err());
}
}
pub enum EndpointType {
Community,
Person,
Post,
Comment,
PrivateMessage,
}
/// Generates an apub endpoint for a given domain, IE xyz.tld
pub fn generate_local_apub_endpoint(
endpoint_type: EndpointType,
name: &str,
domain: &str,
) -> Result<DbUrl, ParseError> {
let point = match endpoint_type {
EndpointType::Community => "c",
EndpointType::Person => "u",
EndpointType::Post => "post",
EndpointType::Comment => "comment",
EndpointType::PrivateMessage => "private_message",
};
Ok(Url::parse(&format!("{}/{}/{}", domain, point, name))?.into())
}
pub fn generate_followers_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
}
pub fn generate_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
}
pub fn generate_site_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
let mut actor_id: Url = actor_id.clone().into();
actor_id.set_path("site_inbox");
Ok(actor_id.into())
}
pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError> {
let actor_id: Url = actor_id.clone().into();
let url = format!(
"{}://{}{}/inbox",
&actor_id.scheme(),
&actor_id.host_str().context(location_info!())?,
if let Some(port) = actor_id.port() {
format!(":{}", port)
} else {
String::new()
},
);
Ok(Url::parse(&url)?.into())
}
pub fn generate_outbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
Ok(Url::parse(&format!("{}/outbox", actor_id))?.into())
}
pub fn generate_moderators_url(community_id: &DbUrl) -> Result<DbUrl, LemmyError> {
Ok(Url::parse(&format!("{}/moderators", community_id))?.into())
}

View file

@ -1,14 +1,15 @@
use crate::{
comment::CommentResponse,
context::LemmyContext,
post::PostResponse,
websocket::{
messages::{CaptchaItem, StandardMessage, WsMessage},
serialize_websocket_message,
OperationType,
UserOperation,
UserOperationApub,
UserOperationCrud,
},
LemmyContext,
};
use actix::prelude::*;
use anyhow::Context as acontext;
@ -50,6 +51,13 @@ type MessageHandlerCrudType = fn(
data: &str,
) -> Pin<Box<dyn Future<Output = Result<String, LemmyError>> + '_>>;
type MessageHandlerApubType = fn(
context: LemmyContext,
id: ConnectionId,
op: UserOperationApub,
data: &str,
) -> Pin<Box<dyn Future<Output = Result<String, LemmyError>> + '_>>;
/// `ChatServer` manages chat rooms and responsible for coordinating chat
/// session.
pub struct ChatServer {
@ -84,6 +92,7 @@ pub struct ChatServer {
message_handler: MessageHandlerType,
message_handler_crud: MessageHandlerCrudType,
message_handler_apub: MessageHandlerApubType,
/// An HTTP Client
client: ClientWithMiddleware,
@ -105,6 +114,7 @@ impl ChatServer {
pool: DbPool,
message_handler: MessageHandlerType,
message_handler_crud: MessageHandlerCrudType,
message_handler_apub: MessageHandlerApubType,
client: ClientWithMiddleware,
settings: Settings,
secret: Secret,
@ -121,6 +131,7 @@ impl ChatServer {
captchas: Vec::new(),
message_handler,
message_handler_crud,
message_handler_apub,
client,
settings,
secret,
@ -453,16 +464,17 @@ impl ChatServer {
None => IpAddr("blank_ip".to_string()),
};
let context = LemmyContext {
pool: self.pool.clone(),
chat_server: ctx.address(),
client: self.client.clone(),
settings: self.settings.clone(),
secret: self.secret.clone(),
rate_limit_cell: self.rate_limit_cell.clone(),
};
let context = LemmyContext::create(
self.pool.clone(),
ctx.address(),
self.client.clone(),
self.settings.clone(),
self.secret.clone(),
self.rate_limit_cell.clone(),
);
let message_handler_crud = self.message_handler_crud;
let message_handler = self.message_handler;
let message_handler_apub = self.message_handler_apub;
let rate_limiter = self.rate_limit_cell.clone();
async move {
let json: Value = serde_json::from_str(&msg.msg)?;
@ -482,15 +494,21 @@ impl ChatServer {
};
let fut = (message_handler_crud)(context, msg.id, user_operation_crud, data);
(passed, fut)
} else {
let user_operation = UserOperation::from_str(op)?;
} else if let Ok(user_operation) = UserOperation::from_str(op) {
let passed = match user_operation {
UserOperation::GetCaptcha => rate_limiter.post().check(ip),
UserOperation::Search => rate_limiter.search().check(ip),
_ => rate_limiter.message().check(ip),
};
let fut = (message_handler)(context, msg.id, user_operation, data);
(passed, fut)
} else {
let user_operation = UserOperationApub::from_str(op)?;
let passed = match user_operation {
UserOperationApub::Search => rate_limiter.search().check(ip),
_ => rate_limiter.message().check(ip),
};
let fut = (message_handler_apub)(context, msg.id, user_operation, data);
(passed, fut)
};
// if rate limit passed, execute api call future

View file

@ -63,8 +63,6 @@ pub enum UserOperation {
ApproveRegistrationApplication,
BanPerson,
GetBannedPersons,
Search,
ResolveObject,
MarkAllAsRead,
SaveUserSettings,
TransferCommunity,
@ -98,27 +96,23 @@ pub enum UserOperationCrud {
// Community
CreateCommunity,
ListCommunities,
GetCommunity,
EditCommunity,
DeleteCommunity,
RemoveCommunity,
// Post
CreatePost,
GetPost,
GetPosts,
EditPost,
DeletePost,
RemovePost,
// Comment
CreateComment,
GetComment,
GetComments,
EditComment,
DeleteComment,
RemoveComment,
// User
Register,
GetPersonDetails,
DeleteAccount,
// Private Message
CreatePrivateMessage,
@ -127,8 +121,20 @@ pub enum UserOperationCrud {
DeletePrivateMessage,
}
#[derive(EnumString, Display, Debug, Clone)]
pub enum UserOperationApub {
GetPosts,
GetCommunity,
GetComments,
GetPersonDetails,
Search,
ResolveObject,
}
pub trait OperationType {}
impl OperationType for UserOperationCrud {}
impl OperationType for UserOperation {}
impl OperationType for UserOperationApub {}

View file

@ -1,9 +1,9 @@
use crate::{
context::LemmyContext,
websocket::{
chat_server::ChatServer,
messages::{Connect, Disconnect, StandardMessage, WsMessage},
},
LemmyContext,
};
use actix::prelude::*;
use actix_web::{web, Error, HttpRequest, HttpResponse};

View file

@ -1,6 +1,7 @@
use crate::{
comment::CommentResponse,
community::CommunityResponse,
context::LemmyContext,
post::PostResponse,
private_message::PrivateMessageResponse,
utils::{check_person_block, get_interface_language, send_email_to_user},
@ -8,7 +9,6 @@ use crate::{
messages::{SendComment, SendCommunityRoomMessage, SendPost, SendUserRoomMessage},
OperationType,
},
LemmyContext,
};
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId, PrivateMessageId},

View file

@ -9,7 +9,6 @@ documentation.workspace = true
repository.workspace = true
[dependencies]
lemmy_apub = { workspace = true }
lemmy_utils = { workspace = true }
lemmy_db_schema = { workspace = true, features = ["full"] }
lemmy_db_views = { workspace = true, features = ["full"] }

View file

@ -2,25 +2,21 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, CreateComment},
generate_local_apub_endpoint,
context::LemmyContext,
utils::{
check_community_ban,
check_community_deleted_or_removed,
check_post_deleted_or_removed,
generate_local_apub_endpoint,
get_local_user_view_from_jwt,
get_post,
local_site_to_slur_regex,
EndpointType,
},
websocket::{
send::{send_comment_ws_message, send_local_notifs},
UserOperationCrud,
},
EndpointType,
LemmyContext,
};
use lemmy_apub::{
objects::comment::ApubComment,
protocol::activities::{create_or_update::note::CreateOrUpdateNote, CreateOrUpdateType},
};
use lemmy_db_schema::{
source::{
@ -157,16 +153,6 @@ impl PerformCrud for CreateComment {
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_like_comment"))?;
let apub_comment: ApubComment = updated_comment.into();
CreateOrUpdateNote::send(
apub_comment.clone(),
&local_user_view.person.clone().into(),
CreateOrUpdateType::Create,
context,
&mut 0,
)
.await?;
// If its a reply, mark the parent as read
if let Some(parent) = parent_opt {
let parent_id = parent.id;

View file

@ -2,18 +2,16 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, DeleteComment},
context::LemmyContext,
utils::{check_community_ban, get_local_user_view_from_jwt},
websocket::{
send::{send_comment_ws_message, send_local_notifs},
UserOperationCrud,
},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
comment::{Comment, CommentUpdateForm},
community::Community,
post::Post,
},
traits::Crud,
@ -88,19 +86,6 @@ impl PerformCrud for DeleteComment {
)
.await?;
// Send the apub message
let community = Community::read(context.pool(), orig_comment.post.community_id).await?;
let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
None,
deleted,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,6 +1,5 @@
mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -2,8 +2,8 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, GetComment},
context::LemmyContext,
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
LemmyContext,
};
use lemmy_db_schema::source::local_site::LocalSite;
use lemmy_db_views::structs::CommentView;

View file

@ -2,18 +2,16 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, RemoveComment},
context::LemmyContext,
utils::{check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
websocket::{
send::{send_comment_ws_message, send_local_notifs},
UserOperationCrud,
},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
comment::{Comment, CommentUpdateForm},
community::Community,
moderator::{ModRemoveComment, ModRemoveCommentForm},
post::Post,
},
@ -96,19 +94,6 @@ impl PerformCrud for RemoveComment {
)
.await?;
// Send the apub message
let community = Community::read(context.pool(), orig_comment.post.community_id).await?;
let deletable = DeletableObjects::Comment(Box::new(updated_comment.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some(String::new())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -2,6 +2,7 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
comment::{CommentResponse, EditComment},
context::LemmyContext,
utils::{
check_community_ban,
check_community_deleted_or_removed,
@ -14,11 +15,6 @@ use lemmy_api_common::{
send::{send_comment_ws_message, send_local_notifs},
UserOperationCrud,
},
LemmyContext,
};
use lemmy_apub::protocol::activities::{
create_or_update::note::CreateOrUpdateNote,
CreateOrUpdateType,
};
use lemmy_db_schema::{
source::{
@ -114,16 +110,6 @@ impl PerformCrud for EditComment {
)
.await?;
// Send the apub update
CreateOrUpdateNote::send(
updated_comment.into(),
&local_user_view.person.into(),
CreateOrUpdateType::Update,
context,
&mut 0,
)
.await?;
send_comment_ws_message(
data.comment_id,
UserOperationCrud::EditComment,

View file

@ -1,17 +1,20 @@
use crate::PerformCrud;
use activitypub_federation::core::{object_id::ObjectId, signatures::generate_actor_keypair};
use activitypub_federation::core::signatures::generate_actor_keypair;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, CreateCommunity},
generate_followers_url,
generate_inbox_url,
generate_local_apub_endpoint,
generate_shared_inbox_url,
utils::{get_local_user_view_from_jwt, is_admin, local_site_to_slur_regex},
EndpointType,
LemmyContext,
context::LemmyContext,
utils::{
generate_followers_url,
generate_inbox_url,
generate_local_apub_endpoint,
generate_shared_inbox_url,
get_local_user_view_from_jwt,
is_admin,
local_site_to_slur_regex,
EndpointType,
},
};
use lemmy_apub::objects::community::ApubCommunity;
use lemmy_db_schema::{
source::community::{
Community,
@ -21,7 +24,7 @@ use lemmy_db_schema::{
CommunityModerator,
CommunityModeratorForm,
},
traits::{Crud, Followable, Joinable},
traits::{ApubActor, Crud, Followable, Joinable},
utils::diesel_option_overwrite_to_url_create,
};
use lemmy_db_views::structs::SiteView;
@ -73,9 +76,8 @@ impl PerformCrud for CreateCommunity {
&data.name,
&context.settings().get_protocol_and_hostname(),
)?;
let community_actor_id_wrapped = ObjectId::<ApubCommunity>::new(community_actor_id.clone());
let community_dupe = community_actor_id_wrapped.dereference_local(context).await;
if community_dupe.is_ok() {
let community_dupe = Community::read_from_apub_id(context.pool(), &community_actor_id).await?;
if community_dupe.is_some() {
return Err(LemmyError::from_message("community_already_exists"));
}

View file

@ -2,11 +2,10 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, DeleteCommunity},
context::LemmyContext,
utils::get_local_user_view_from_jwt,
websocket::{send::send_community_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::community::{Community, CommunityUpdateForm},
traits::Crud,
@ -41,7 +40,7 @@ impl PerformCrud for DeleteCommunity {
// Do the delete
let community_id = data.community_id;
let deleted = data.deleted;
let updated_community = Community::update(
Community::update(
context.pool(),
community_id,
&CommunityUpdateForm::builder()
@ -60,18 +59,6 @@ impl PerformCrud for DeleteCommunity {
)
.await?;
// Send apub messages
let deletable = DeletableObjects::Community(Box::new(updated_community.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
updated_community,
deletable,
None,
deleted,
context,
)
.await?;
Ok(res)
}
}

View file

@ -2,8 +2,8 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
community::{ListCommunities, ListCommunitiesResponse},
context::LemmyContext,
utils::{check_private_instance, get_local_user_view_from_jwt_opt},
LemmyContext,
};
use lemmy_db_schema::{source::local_site::LocalSite, traits::DeleteableOrRemoveable};
use lemmy_db_views_actor::community_view::CommunityQuery;

View file

@ -1,6 +1,5 @@
mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -2,11 +2,10 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, RemoveCommunity},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, is_admin},
websocket::{send::send_community_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::{Community, CommunityUpdateForm},
@ -36,7 +35,7 @@ impl PerformCrud for RemoveCommunity {
// Do the remove
let community_id = data.community_id;
let removed = data.removed;
let updated_community = Community::update(
Community::update(
context.pool(),
community_id,
&CommunityUpdateForm::builder()
@ -66,17 +65,6 @@ impl PerformCrud for RemoveCommunity {
)
.await?;
// Apub messages
let deletable = DeletableObjects::Community(Box::new(updated_community.clone().into()));
send_apub_delete_in_community(
local_user_view.person,
updated_community,
deletable,
data.reason.clone().or_else(|| Some(String::new())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -2,11 +2,10 @@ use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
community::{CommunityResponse, EditCommunity},
context::LemmyContext,
utils::{get_local_user_view_from_jwt, local_site_to_slur_regex},
websocket::{send::send_community_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::protocol::activities::community::update::UpdateCommunity;
use lemmy_db_schema::{
newtypes::PersonId,
source::{
@ -74,17 +73,10 @@ impl PerformCrud for EditCommunity {
.build();
let community_id = data.community_id;
let updated_community = Community::update(context.pool(), community_id, &community_form)
Community::update(context.pool(), community_id, &community_form)
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_community"))?;
UpdateCommunity::send(
updated_community.into(),
&local_user_view.person.into(),
context,
)
.await?;
let op = UserOperationCrud::EditCommunity;
send_community_ws_message(data.community_id, op, websocket_id, None, context).await
}

View file

@ -1,28 +1,6 @@
use actix_web::{web, web::Data};
use lemmy_api_common::{
comment::{CreateComment, DeleteComment, EditComment, GetComment, GetComments, RemoveComment},
community::{
CreateCommunity,
DeleteCommunity,
EditCommunity,
GetCommunity,
ListCommunities,
RemoveCommunity,
},
person::{DeleteAccount, GetPersonDetails, Register},
post::{CreatePost, DeletePost, EditPost, GetPost, GetPosts, RemovePost},
private_message::{
CreatePrivateMessage,
DeletePrivateMessage,
EditPrivateMessage,
GetPrivateMessages,
},
site::{CreateSite, EditSite, GetSite},
websocket::{serialize_websocket_message, UserOperationCrud},
LemmyContext,
};
use actix_web::web::Data;
use lemmy_api_common::context::LemmyContext;
use lemmy_utils::{error::LemmyError, ConnectionId};
use serde::Deserialize;
mod comment;
mod community;
@ -41,115 +19,3 @@ pub trait PerformCrud {
websocket_id: Option<ConnectionId>,
) -> Result<Self::Response, LemmyError>;
}
pub async fn match_websocket_operation_crud(
context: LemmyContext,
id: ConnectionId,
op: UserOperationCrud,
data: &str,
) -> Result<String, LemmyError> {
//TODO: handle commented out actions in crud crate
match op {
// User ops
UserOperationCrud::Register => do_websocket_operation::<Register>(context, id, op, data).await,
UserOperationCrud::GetPersonDetails => {
do_websocket_operation::<GetPersonDetails>(context, id, op, data).await
}
UserOperationCrud::DeleteAccount => {
do_websocket_operation::<DeleteAccount>(context, id, op, data).await
}
// Private Message ops
UserOperationCrud::CreatePrivateMessage => {
do_websocket_operation::<CreatePrivateMessage>(context, id, op, data).await
}
UserOperationCrud::EditPrivateMessage => {
do_websocket_operation::<EditPrivateMessage>(context, id, op, data).await
}
UserOperationCrud::DeletePrivateMessage => {
do_websocket_operation::<DeletePrivateMessage>(context, id, op, data).await
}
UserOperationCrud::GetPrivateMessages => {
do_websocket_operation::<GetPrivateMessages>(context, id, op, data).await
}
// Site ops
UserOperationCrud::CreateSite => {
do_websocket_operation::<CreateSite>(context, id, op, data).await
}
UserOperationCrud::EditSite => do_websocket_operation::<EditSite>(context, id, op, data).await,
UserOperationCrud::GetSite => do_websocket_operation::<GetSite>(context, id, op, data).await,
// Community ops
UserOperationCrud::GetCommunity => {
do_websocket_operation::<GetCommunity>(context, id, op, data).await
}
UserOperationCrud::ListCommunities => {
do_websocket_operation::<ListCommunities>(context, id, op, data).await
}
UserOperationCrud::CreateCommunity => {
do_websocket_operation::<CreateCommunity>(context, id, op, data).await
}
UserOperationCrud::EditCommunity => {
do_websocket_operation::<EditCommunity>(context, id, op, data).await
}
UserOperationCrud::DeleteCommunity => {
do_websocket_operation::<DeleteCommunity>(context, id, op, data).await
}
UserOperationCrud::RemoveCommunity => {
do_websocket_operation::<RemoveCommunity>(context, id, op, data).await
}
// Post ops
UserOperationCrud::CreatePost => {
do_websocket_operation::<CreatePost>(context, id, op, data).await
}
UserOperationCrud::GetPost => do_websocket_operation::<GetPost>(context, id, op, data).await,
UserOperationCrud::GetPosts => do_websocket_operation::<GetPosts>(context, id, op, data).await,
UserOperationCrud::EditPost => do_websocket_operation::<EditPost>(context, id, op, data).await,
UserOperationCrud::DeletePost => {
do_websocket_operation::<DeletePost>(context, id, op, data).await
}
UserOperationCrud::RemovePost => {
do_websocket_operation::<RemovePost>(context, id, op, data).await
}
// Comment ops
UserOperationCrud::CreateComment => {
do_websocket_operation::<CreateComment>(context, id, op, data).await
}
UserOperationCrud::EditComment => {
do_websocket_operation::<EditComment>(context, id, op, data).await
}
UserOperationCrud::DeleteComment => {
do_websocket_operation::<DeleteComment>(context, id, op, data).await
}
UserOperationCrud::RemoveComment => {
do_websocket_operation::<RemoveComment>(context, id, op, data).await
}
UserOperationCrud::GetComment => {
do_websocket_operation::<GetComment>(context, id, op, data).await
}
UserOperationCrud::GetComments => {
do_websocket_operation::<GetComments>(context, id, op, data).await
}
}
}
async fn do_websocket_operation<'a, 'b, Data>(
context: LemmyContext,
id: ConnectionId,
op: UserOperationCrud,
data: &str,
) -> Result<String, LemmyError>
where
for<'de> Data: Deserialize<'de> + 'a,
Data: PerformCrud,
{
let parsed_data: Data = serde_json::from_str(data)?;
let res = parsed_data
.perform(&web::Data::new(context), Some(id))
.await?;
serialize_websocket_message(&op, &res)
}

View file

@ -1,24 +1,20 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
generate_local_apub_endpoint,
context::LemmyContext,
post::{CreatePost, PostResponse},
request::fetch_site_data,
utils::{
check_community_ban,
check_community_deleted_or_removed,
generate_local_apub_endpoint,
get_local_user_view_from_jwt,
honeypot_check,
local_site_to_slur_regex,
mark_post_as_read,
EndpointType,
},
websocket::{send::send_post_ws_message, UserOperationCrud},
EndpointType,
LemmyContext,
};
use lemmy_apub::{
objects::post::ApubPost,
protocol::activities::{create_or_update::page::CreateOrUpdatePage, CreateOrUpdateType},
};
use lemmy_db_schema::{
impls::actor_language::default_post_language,
@ -174,15 +170,6 @@ impl PerformCrud for CreatePost {
}
}
let apub_post: ApubPost = updated_post.into();
CreateOrUpdatePage::send(
apub_post.clone(),
&local_user_view.person.clone().into(),
CreateOrUpdateType::Create,
context,
)
.await?;
send_post_ws_message(
inserted_post.id,
UserOperationCrud::CreatePost,

View file

@ -1,17 +1,13 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{DeletePost, PostResponse},
utils::{check_community_ban, check_community_deleted_or_removed, get_local_user_view_from_jwt},
websocket::{send::send_post_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
post::{Post, PostUpdateForm},
},
source::post::{Post, PostUpdateForm},
traits::Crud,
};
use lemmy_utils::{error::LemmyError, ConnectionId};
@ -54,7 +50,7 @@ impl PerformCrud for DeletePost {
// Update the post
let post_id = data.post_id;
let deleted = data.deleted;
let updated_post = Post::update(
Post::update(
context.pool(),
post_id,
&PostUpdateForm::builder().deleted(Some(deleted)).build(),
@ -70,18 +66,6 @@ impl PerformCrud for DeletePost {
)
.await?;
// apub updates
let community = Community::read(context.pool(), orig_post.community_id).await?;
let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
None,
deleted,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,6 +1,5 @@
mod create;
mod delete;
mod list;
mod read;
mod remove;
mod update;

View file

@ -1,10 +1,10 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{GetPost, GetPostResponse},
utils::{check_private_instance, get_local_user_view_from_jwt_opt, mark_post_as_read},
websocket::messages::GetPostUsersOnline,
LemmyContext,
};
use lemmy_db_schema::{
aggregates::structs::{PersonPostAggregates, PersonPostAggregatesForm},

View file

@ -1,15 +1,13 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{PostResponse, RemovePost},
utils::{check_community_ban, get_local_user_view_from_jwt, is_mod_or_admin},
websocket::{send::send_post_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::activities::deletion::{send_apub_delete_in_community, DeletableObjects};
use lemmy_db_schema::{
source::{
community::Community,
moderator::{ModRemovePost, ModRemovePostForm},
post::{Post, PostUpdateForm},
},
@ -52,7 +50,7 @@ impl PerformCrud for RemovePost {
// Update the post
let post_id = data.post_id;
let removed = data.removed;
let updated_post = Post::update(
Post::update(
context.pool(),
post_id,
&PostUpdateForm::builder().removed(Some(removed)).build(),
@ -77,18 +75,6 @@ impl PerformCrud for RemovePost {
)
.await?;
// apub updates
let community = Community::read(context.pool(), orig_post.community_id).await?;
let deletable = DeletableObjects::Post(Box::new(updated_post.into()));
send_apub_delete_in_community(
local_user_view.person,
community,
deletable,
data.reason.clone().or_else(|| Some(String::new())),
removed,
context,
)
.await?;
Ok(res)
}
}

View file

@ -1,6 +1,7 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
post::{EditPost, PostResponse},
request::fetch_site_data,
utils::{
@ -10,11 +11,6 @@ use lemmy_api_common::{
local_site_to_slur_regex,
},
websocket::{send::send_post_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::protocol::activities::{
create_or_update::page::CreateOrUpdatePage,
CreateOrUpdateType,
};
use lemmy_db_schema::{
source::{
@ -109,27 +105,15 @@ impl PerformCrud for EditPost {
let post_id = data.post_id;
let res = Post::update(context.pool(), post_id, &post_form).await;
let updated_post: Post = match res {
Ok(post) => post,
Err(e) => {
let err_type = if e.to_string() == "value too long for type character varying(200)" {
"post_title_too_long"
} else {
"couldnt_update_post"
};
if let Err(e) = res {
let err_type = if e.to_string() == "value too long for type character varying(200)" {
"post_title_too_long"
} else {
"couldnt_update_post"
};
return Err(LemmyError::from_error_message(e, err_type));
}
};
// Send apub update
CreateOrUpdatePage::send(
updated_post.into(),
&local_user_view.person.clone().into(),
CreateOrUpdateType::Update,
context,
)
.await?;
return Err(LemmyError::from_error_message(e, err_type));
}
send_post_ws_message(
data.post_id,

View file

@ -1,22 +1,18 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
generate_local_apub_endpoint,
context::LemmyContext,
private_message::{CreatePrivateMessage, PrivateMessageResponse},
utils::{
check_person_block,
generate_local_apub_endpoint,
get_interface_language,
get_local_user_view_from_jwt,
local_site_to_slur_regex,
send_email_to_user,
EndpointType,
},
websocket::{send::send_pm_ws_message, UserOperationCrud},
EndpointType,
LemmyContext,
};
use lemmy_apub::protocol::activities::{
create_or_update::chat_message::CreateOrUpdateChatMessage,
CreateOrUpdateType,
};
use lemmy_db_schema::{
source::{
@ -74,7 +70,7 @@ impl PerformCrud for CreatePrivateMessage {
&inserted_private_message_id.to_string(),
&protocol_and_hostname,
)?;
let updated_private_message = PrivateMessage::update(
PrivateMessage::update(
context.pool(),
inserted_private_message.id,
&PrivateMessageUpdateForm::builder()
@ -84,14 +80,6 @@ impl PerformCrud for CreatePrivateMessage {
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_create_private_message"))?;
CreateOrUpdateChatMessage::send(
updated_private_message.into(),
&local_user_view.person.into(),
CreateOrUpdateType::Create,
context,
)
.await?;
let res = send_pm_ws_message(
inserted_private_message.id,
UserOperationCrud::CreatePrivateMessage,

View file

@ -1,12 +1,11 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{DeletePrivateMessage, PrivateMessageResponse},
utils::get_local_user_view_from_jwt,
websocket::{send::send_pm_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::activities::deletion::send_apub_delete_private_message;
use lemmy_db_schema::{
source::private_message::{PrivateMessage, PrivateMessageUpdateForm},
traits::Crud,
@ -37,7 +36,7 @@ impl PerformCrud for DeletePrivateMessage {
// Doing the update
let private_message_id = data.private_message_id;
let deleted = data.deleted;
let updated_private_message = PrivateMessage::update(
PrivateMessage::update(
context.pool(),
private_message_id,
&PrivateMessageUpdateForm::builder()
@ -47,15 +46,6 @@ impl PerformCrud for DeletePrivateMessage {
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
// Send the apub update
send_apub_delete_private_message(
&local_user_view.person.into(),
updated_private_message,
data.deleted,
context,
)
.await?;
let op = UserOperationCrud::DeletePrivateMessage;
send_pm_ws_message(data.private_message_id, op, websocket_id, context).await
}

View file

@ -1,9 +1,9 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{GetPrivateMessages, PrivateMessagesResponse},
utils::get_local_user_view_from_jwt,
LemmyContext,
};
use lemmy_db_schema::traits::DeleteableOrRemoveable;
use lemmy_db_views::private_message_view::PrivateMessageQuery;

View file

@ -1,14 +1,10 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
private_message::{EditPrivateMessage, PrivateMessageResponse},
utils::{get_local_user_view_from_jwt, local_site_to_slur_regex},
websocket::{send::send_pm_ws_message, UserOperationCrud},
LemmyContext,
};
use lemmy_apub::protocol::activities::{
create_or_update::chat_message::CreateOrUpdateChatMessage,
CreateOrUpdateType,
};
use lemmy_db_schema::{
source::{
@ -45,7 +41,7 @@ impl PerformCrud for EditPrivateMessage {
// Doing the update
let content_slurs_removed = remove_slurs(&data.content, &local_site_to_slur_regex(&local_site));
let private_message_id = data.private_message_id;
let updated_private_message = PrivateMessage::update(
PrivateMessage::update(
context.pool(),
private_message_id,
&PrivateMessageUpdateForm::builder()
@ -56,15 +52,6 @@ impl PerformCrud for EditPrivateMessage {
.await
.map_err(|e| LemmyError::from_error_message(e, "couldnt_update_private_message"))?;
// Send the apub update
CreateOrUpdateChatMessage::send(
updated_private_message.into(),
&local_user_view.person.into(),
CreateOrUpdateType::Update,
context,
)
.await?;
let op = UserOperationCrud::EditPrivateMessage;
send_pm_ws_message(data.private_message_id, op, websocket_id, context).await
}

View file

@ -2,16 +2,16 @@ use crate::PerformCrud;
use activitypub_federation::core::signatures::generate_actor_keypair;
use actix_web::web::Data;
use lemmy_api_common::{
generate_site_inbox_url,
context::LemmyContext,
site::{CreateSite, SiteResponse},
utils::{
generate_site_inbox_url,
get_local_user_view_from_jwt,
is_admin,
local_site_rate_limit_to_rate_limit_config,
local_site_to_slur_regex,
site_description_length_check,
},
LemmyContext,
};
use lemmy_db_schema::{
newtypes::DbUrl,

View file

@ -1,10 +1,10 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{GetSite, GetSiteResponse, MyUserInfo},
utils::{build_federated_instances, get_local_user_settings_view_from_jwt_opt},
websocket::messages::GetUsersOnline,
LemmyContext,
};
use lemmy_db_schema::source::{actor_language::SiteLanguage, language::Language, tagline::Tagline};
use lemmy_db_views::structs::{LocalUserDiscussionLanguageView, SiteView};

View file

@ -1,6 +1,7 @@
use crate::PerformCrud;
use actix_web::web::Data;
use lemmy_api_common::{
context::LemmyContext,
site::{EditSite, SiteResponse},
utils::{
get_local_user_view_from_jwt,
@ -10,7 +11,6 @@ use lemmy_api_common::{
site_description_length_check,
},
websocket::{messages::SendAllMessage, UserOperationCrud},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -2,20 +2,20 @@ use crate::PerformCrud;
use activitypub_federation::core::signatures::generate_actor_keypair;
use actix_web::web::Data;
use lemmy_api_common::{
generate_inbox_url,
generate_local_apub_endpoint,
generate_shared_inbox_url,
context::LemmyContext,
person::{LoginResponse, Register},
utils::{
generate_inbox_url,
generate_local_apub_endpoint,
generate_shared_inbox_url,
honeypot_check,
local_site_to_slur_regex,
password_length_check,
send_new_applicant_email_to_admins,
send_verification_email,
EndpointType,
},
websocket::messages::CheckCaptcha,
EndpointType,
LemmyContext,
};
use lemmy_db_schema::{
aggregates::structs::PersonAggregates,

View file

@ -2,11 +2,10 @@ use crate::PerformCrud;
use actix_web::web::Data;
use bcrypt::verify;
use lemmy_api_common::{
context::LemmyContext,
person::{DeleteAccount, DeleteAccountResponse},
utils::{delete_user_account, get_local_user_view_from_jwt},
LemmyContext,
utils::get_local_user_view_from_jwt,
};
use lemmy_apub::protocol::activities::deletion::delete_user::DeleteUser;
use lemmy_utils::{error::LemmyError, ConnectionId};
#[async_trait::async_trait(?Send)]
@ -33,15 +32,6 @@ impl PerformCrud for DeleteAccount {
return Err(LemmyError::from_message("password_incorrect"));
}
delete_user_account(
local_user_view.person.id,
context.pool(),
context.settings(),
context.client(),
)
.await?;
DeleteUser::send(&local_user_view.person.into(), context).await?;
Ok(DeleteAccountResponse {})
}
}

View file

@ -1,3 +1,2 @@
mod create;
mod delete;
mod read;

View file

@ -24,8 +24,8 @@ use activitystreams_kinds::{activity::BlockType, public};
use anyhow::anyhow;
use chrono::NaiveDateTime;
use lemmy_api_common::{
context::LemmyContext,
utils::{remove_user_data, remove_user_data_in_community},
LemmyContext,
};
use lemmy_db_schema::{
source::{

View file

@ -1,13 +1,27 @@
use crate::{
objects::{community::ApubCommunity, instance::ApubSite},
protocol::objects::{group::Group, instance::Instance},
objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
protocol::{
activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
objects::{group::Group, instance::Instance},
},
ActorType,
SendActivity,
};
use activitypub_federation::{core::object_id::ObjectId, traits::ApubObject};
use chrono::NaiveDateTime;
use lemmy_api_common::LemmyContext;
use lemmy_db_schema::{source::site::Site, utils::DbPool};
use lemmy_utils::error::LemmyError;
use lemmy_api_common::{
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
person::{BanPerson, BanPersonResponse},
utils::get_local_user_view_from_jwt,
};
use lemmy_db_schema::{
source::{community::Community, person::Person, site::Site},
traits::Crud,
utils::DbPool,
};
use lemmy_db_views::structs::SiteView;
use lemmy_utils::{error::LemmyError, utils::naive_from_unix};
use serde::Deserialize;
use url::Url;
@ -123,3 +137,90 @@ async fn generate_cc(target: &SiteOrCommunity, pool: &DbPool) -> Result<Vec<Url>
SiteOrCommunity::Community(c) => vec![c.actor_id()],
})
}
#[async_trait::async_trait(?Send)]
impl SendActivity for BanPerson {
type Response = BanPersonResponse;
async fn send_activity(
request: &Self,
_response: &Self::Response,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let local_user_view =
get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
let person = Person::read(context.pool(), request.person_id).await?;
let site = SiteOrCommunity::Site(SiteView::read_local(context.pool()).await?.site.into());
let expires = request.expires.map(naive_from_unix);
// if the action affects a local user, federate to other instances
if person.local {
if request.ban {
BlockUser::send(
&site,
&person.into(),
&local_user_view.person.into(),
request.remove_data.unwrap_or(false),
request.reason.clone(),
expires,
context,
)
.await
} else {
UndoBlockUser::send(
&site,
&person.into(),
&local_user_view.person.into(),
request.reason.clone(),
context,
)
.await
}
} else {
Ok(())
}
}
}
#[async_trait::async_trait(?Send)]
impl SendActivity for BanFromCommunity {
type Response = BanFromCommunityResponse;
async fn send_activity(
request: &Self,
_response: &Self::Response,
context: &LemmyContext,
) -> Result<(), LemmyError> {
let local_user_view =
get_local_user_view_from_jwt(&request.auth, context.pool(), context.secret()).await?;
let community: ApubCommunity = Community::read(context.pool(), request.community_id)
.await?
.into();
let banned_person: ApubPerson = Person::read(context.pool(), request.person_id)
.await?
.into();
let expires = request.expires.map(naive_from_unix);
if request.ban {
BlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
request.remove_data.unwrap_or(false),
request.reason.clone(),
expires,
context,
)
.await
} else {
UndoBlockUser::send(
&SiteOrCommunity::Community(community),
&banned_person,
&local_user_view.person.clone().into(),
request.reason.clone(),
context,
)
.await
}
}
}

View file

@ -19,7 +19,7 @@ use activitypub_federation::{
utils::verify_domains_match,
};
use activitystreams_kinds::{activity::UndoType, public};
use lemmy_api_common::LemmyContext;
use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
community::{CommunityPersonBan, CommunityPersonBanForm},

Some files were not shown because too many files have changed in this diff Show more