done
fi
-echo "killall existing lemmy_server processes"
-killall -s1 lemmy_server || true
-
echo "$PWD"
echo "start alpha"
cargo build
rm target/lemmy_server || true
cp target/debug/lemmy_server target/lemmy_server
+killall -s1 lemmy_server || true
./api_tests/prepare-drone-federation-test.sh
popd
yarn
yarn api-test || true
+killall -s1 lemmy_server || true
for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do
psql "$LEMMY_DATABASE_URL" -c "DROP DATABASE $INSTANCE"
done
-use crate::{check_report_reason, Perform};
-use actix_web::web::Data;
+use crate::check_report_reason;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
comment::{CommentReportResponse, CreateCommentReport},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
local_user_view_from_jwt,
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
/// Creates a comment report and notifies the moderators of the community
-#[async_trait::async_trait(?Send)]
-impl Perform for CreateCommentReport {
- type Response = CommentReportResponse;
+#[tracing::instrument(skip(context))]
+pub async fn create_comment_report(
+ data: Json<CreateCommentReport>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommentReportResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<CommentReportResponse, LemmyError> {
- let data: &CreateCommentReport = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ let reason = sanitize_html(data.reason.trim());
+ check_report_reason(&reason, &local_site)?;
- let reason = sanitize_html(self.reason.trim());
- check_report_reason(&reason, &local_site)?;
+ let person_id = local_user_view.person.id;
+ let comment_id = data.comment_id;
+ let comment_view = CommentView::read(&mut context.pool(), comment_id, None).await?;
- let person_id = local_user_view.person.id;
- let comment_id = data.comment_id;
- let comment_view = CommentView::read(&mut context.pool(), comment_id, None).await?;
+ check_community_ban(person_id, comment_view.community.id, &mut context.pool()).await?;
- check_community_ban(person_id, comment_view.community.id, &mut context.pool()).await?;
+ let report_form = CommentReportForm {
+ creator_id: person_id,
+ comment_id,
+ original_comment_text: comment_view.comment.content,
+ reason,
+ };
- let report_form = CommentReportForm {
- creator_id: person_id,
- comment_id,
- original_comment_text: comment_view.comment.content,
- reason,
- };
+ let report = CommentReport::report(&mut context.pool(), &report_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
- let report = CommentReport::report(&mut context.pool(), &report_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
+ let comment_report_view =
+ CommentReportView::read(&mut context.pool(), report.id, person_id).await?;
- let comment_report_view =
- CommentReportView::read(&mut context.pool(), report.id, person_id).await?;
+ // Email the admins
+ if local_site.reports_email_admins {
+ send_new_report_email_to_admins(
+ &comment_report_view.creator.name,
+ &comment_report_view.comment_creator.name,
+ &mut context.pool(),
+ context.settings(),
+ )
+ .await?;
+ }
- // Email the admins
- if local_site.reports_email_admins {
- send_new_report_email_to_admins(
- &comment_report_view.creator.name,
- &comment_report_view.comment_creator.name,
- &mut context.pool(),
- context.settings(),
- )
- .await?;
- }
+ ActivityChannel::submit_activity(
+ SendActivityData::CreateReport(
+ comment_view.comment.ap_id.inner().clone(),
+ local_user_view.person,
+ comment_view.community,
+ data.reason.clone(),
+ ),
+ &context,
+ )
+ .await?;
- Ok(CommentReportResponse {
- comment_report_view,
- })
- }
+ Ok(Json(CommentReportResponse {
+ comment_report_view,
+ }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{is_mod_or_admin, local_user_view_from_jwt},
};
use lemmy_db_schema::{
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for AddModToCommunity {
- type Response = AddModToCommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn add_mod_to_community(
+ data: Json<AddModToCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<AddModToCommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<AddModToCommunityResponse, LemmyError> {
- let data: &AddModToCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let community_id = data.community_id;
- let community_id = data.community_id;
+ // Verify that only mods or admins can add mod
+ is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id).await?;
+ let community = Community::read(&mut context.pool(), community_id).await?;
+ if local_user_view.person.admin && !community.local {
+ return Err(LemmyErrorType::NotAModerator)?;
+ }
- // Verify that only mods or admins can add mod
- is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id).await?;
- let community = Community::read(&mut context.pool(), community_id).await?;
- if local_user_view.person.admin && !community.local {
- return Err(LemmyErrorType::NotAModerator)?;
- }
+ // Update in local database
+ let community_moderator_form = CommunityModeratorForm {
+ community_id: data.community_id,
+ person_id: data.person_id,
+ };
+ if data.added {
+ CommunityModerator::join(&mut context.pool(), &community_moderator_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
+ } else {
+ CommunityModerator::leave(&mut context.pool(), &community_moderator_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
+ }
- // Update in local database
- let community_moderator_form = CommunityModeratorForm {
- community_id: data.community_id,
- person_id: data.person_id,
- };
- if data.added {
- CommunityModerator::join(&mut context.pool(), &community_moderator_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
- } else {
- CommunityModerator::leave(&mut context.pool(), &community_moderator_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
- }
+ // Mod tables
+ let form = ModAddCommunityForm {
+ mod_person_id: local_user_view.person.id,
+ other_person_id: data.person_id,
+ community_id: data.community_id,
+ removed: Some(!data.added),
+ };
- // Mod tables
- let form = ModAddCommunityForm {
- mod_person_id: local_user_view.person.id,
- other_person_id: data.person_id,
- community_id: data.community_id,
- removed: Some(!data.added),
- };
+ ModAddCommunity::create(&mut context.pool(), &form).await?;
- ModAddCommunity::create(&mut context.pool(), &form).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;
+ let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).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;
- let moderators =
- CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::AddModToCommunity(
+ local_user_view.person,
+ data.community_id,
+ data.person_id,
+ data.added,
+ ),
+ &context,
+ )
+ .await?;
- Ok(AddModToCommunityResponse { moderators })
- }
+ Ok(Json(AddModToCommunityResponse { moderators }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
community::{BanFromCommunity, BanFromCommunityResponse},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
is_mod_or_admin,
local_user_view_from_jwt,
utils::{time::naive_from_unix, validation::is_valid_body_field},
};
-#[async_trait::async_trait(?Send)]
-impl Perform for BanFromCommunity {
- type Response = BanFromCommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn ban_from_community(
+ data: Json<BanFromCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<BanFromCommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<BanFromCommunityResponse, LemmyError> {
- let data: &BanFromCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let banned_person_id = data.person_id;
+ let remove_data = data.remove_data.unwrap_or(false);
+ let expires = data.expires.map(naive_from_unix);
- let community_id = data.community_id;
- let banned_person_id = data.person_id;
- let remove_data = data.remove_data.unwrap_or(false);
- let expires = data.expires.map(naive_from_unix);
+ // Verify that only mods or admins can ban
+ is_mod_or_admin(
+ &mut context.pool(),
+ local_user_view.person.id,
+ data.community_id,
+ )
+ .await?;
+ is_valid_body_field(&data.reason, false)?;
- // Verify that only mods or admins can ban
- is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id).await?;
- is_valid_body_field(&data.reason, false)?;
+ let community_user_ban_form = CommunityPersonBanForm {
+ community_id: data.community_id,
+ person_id: data.person_id,
+ expires: Some(expires),
+ };
- let community_user_ban_form = CommunityPersonBanForm {
+ if data.ban {
+ CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
+
+ // Also unsubscribe them from the community, if they are subscribed
+ let community_follower_form = CommunityFollowerForm {
community_id: data.community_id,
- person_id: data.person_id,
- expires: Some(expires),
+ person_id: banned_person_id,
+ pending: false,
};
- if data.ban {
- CommunityPersonBan::ban(&mut context.pool(), &community_user_ban_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
+ CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
+ .await
+ .ok();
+ } else {
+ CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
+ }
- // Also unsubscribe them from the community, if they are subscribed
- let community_follower_form = CommunityFollowerForm {
- community_id: data.community_id,
- person_id: banned_person_id,
- pending: false,
- };
+ // Remove/Restore their data if that's desired
+ if remove_data {
+ remove_user_data_in_community(data.community_id, banned_person_id, &mut context.pool()).await?;
+ }
- CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
- .await
- .ok();
- } else {
- CommunityPersonBan::unban(&mut context.pool(), &community_user_ban_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityUserAlreadyBanned)?;
- }
+ // Mod tables
+ let form = ModBanFromCommunityForm {
+ mod_person_id: local_user_view.person.id,
+ other_person_id: data.person_id,
+ community_id: data.community_id,
+ reason: sanitize_html_opt(&data.reason),
+ banned: Some(data.ban),
+ expires,
+ };
- // Remove/Restore their data if that's desired
- if remove_data {
- remove_user_data_in_community(community_id, banned_person_id, &mut context.pool()).await?;
- }
+ ModBanFromCommunity::create(&mut context.pool(), &form).await?;
- // Mod tables
- let form = ModBanFromCommunityForm {
- mod_person_id: local_user_view.person.id,
- other_person_id: data.person_id,
- community_id: data.community_id,
- reason: sanitize_html_opt(&data.reason),
- banned: Some(data.ban),
- expires,
- };
-
- ModBanFromCommunity::create(&mut context.pool(), &form).await?;
+ let person_view = PersonView::read(&mut context.pool(), data.person_id).await?;
- let person_id = data.person_id;
- let person_view = PersonView::read(&mut context.pool(), person_id).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::BanFromCommunity(
+ local_user_view.person,
+ data.community_id,
+ person_view.person.clone(),
+ data.0.clone(),
+ ),
+ &context,
+ )
+ .await?;
- Ok(BanFromCommunityResponse {
- person_view,
- banned: data.ban,
- })
- }
+ Ok(Json(BanFromCommunityResponse {
+ person_view,
+ banned: data.ban,
+ }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
community::{BlockCommunity, BlockCommunityResponse},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::local_user_view_from_jwt,
};
use lemmy_db_schema::{
use lemmy_db_views_actor::structs::CommunityView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for BlockCommunity {
- type Response = BlockCommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn block_community(
+ data: Json<BlockCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<BlockCommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<BlockCommunityResponse, LemmyError> {
- let data: &BlockCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let community_id = data.community_id;
+ let person_id = local_user_view.person.id;
+ let community_block_form = CommunityBlockForm {
+ person_id,
+ community_id,
+ };
- let community_id = data.community_id;
- let person_id = local_user_view.person.id;
- let community_block_form = CommunityBlockForm {
+ if data.block {
+ CommunityBlock::block(&mut context.pool(), &community_block_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
+
+ // Also, unfollow the community, and send a federated unfollow
+ let community_follower_form = CommunityFollowerForm {
+ community_id: data.community_id,
person_id,
- community_id,
+ pending: false,
};
- if data.block {
- CommunityBlock::block(&mut context.pool(), &community_block_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
-
- // Also, unfollow the community, and send a federated unfollow
- let community_follower_form = CommunityFollowerForm {
- community_id: data.community_id,
- person_id,
- pending: false,
- };
+ CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
+ .await
+ .ok();
+ } else {
+ CommunityBlock::unblock(&mut context.pool(), &community_block_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
+ }
- CommunityFollower::unfollow(&mut context.pool(), &community_follower_form)
- .await
- .ok();
- } else {
- CommunityBlock::unblock(&mut context.pool(), &community_block_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
- }
+ let community_view =
+ CommunityView::read(&mut context.pool(), community_id, Some(person_id), None).await?;
- let community_view =
- CommunityView::read(&mut context.pool(), community_id, Some(person_id), None).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::FollowCommunity(
+ community_view.community.clone(),
+ local_user_view.person.clone(),
+ false,
+ ),
+ &context,
+ )
+ .await?;
- Ok(BlockCommunityResponse {
- blocked: data.block,
- community_view,
- })
- }
+ Ok(Json(BlockCommunityResponse {
+ blocked: data.block,
+ community_view,
+ }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_community_response,
community::{CommunityResponse, HideCommunity},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{is_admin, local_user_view_from_jwt, sanitize_html_opt},
};
use lemmy_db_schema::{
};
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl Perform for HideCommunity {
- type Response = CommunityResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
- let data: &HideCommunity = self;
-
- // Verify its a admin (only admin can hide or unhide it)
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- is_admin(&local_user_view)?;
-
- let community_form = CommunityUpdateForm::builder()
- .hidden(Some(data.hidden))
- .build();
-
- let mod_hide_community_form = ModHideCommunityForm {
- community_id: data.community_id,
- mod_person_id: local_user_view.person.id,
- reason: sanitize_html_opt(&data.reason),
- hidden: Some(data.hidden),
- };
-
- let community_id = data.community_id;
- Community::update(&mut context.pool(), community_id, &community_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunityHiddenStatus)?;
-
- ModHideCommunity::create(&mut context.pool(), &mod_hide_community_form).await?;
-
- build_community_response(context, local_user_view, community_id).await
- }
+#[tracing::instrument(skip(context))]
+pub async fn hide_community(
+ data: Json<HideCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommunityResponse>, LemmyError> {
+ // Verify its a admin (only admin can hide or unhide it)
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ is_admin(&local_user_view)?;
+
+ let community_form = CommunityUpdateForm::builder()
+ .hidden(Some(data.hidden))
+ .build();
+
+ let mod_hide_community_form = ModHideCommunityForm {
+ community_id: data.community_id,
+ mod_person_id: local_user_view.person.id,
+ reason: sanitize_html_opt(&data.reason),
+ hidden: Some(data.hidden),
+ };
+
+ let community_id = data.community_id;
+ let community = Community::update(&mut context.pool(), community_id, &community_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunityHiddenStatus)?;
+
+ ModHideCommunity::create(&mut context.pool(), &mod_hide_community_form).await?;
+
+ ActivityChannel::submit_activity(
+ SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
+ &context,
+ )
+ .await?;
+
+ build_community_response(&context, local_user_view, community_id).await
}
-mod add_mod;
-mod ban;
-mod block;
+pub mod add_mod;
+pub mod ban;
+pub mod block;
pub mod follow;
-mod hide;
-mod transfer;
+pub mod hide;
+pub mod transfer;
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
person::{BanPerson, BanPersonResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{is_admin, local_user_view_from_jwt, remove_user_data, sanitize_html_opt},
};
use lemmy_db_schema::{
error::{LemmyError, LemmyErrorExt, LemmyErrorType},
utils::{time::naive_from_unix, validation::is_valid_body_field},
};
+#[tracing::instrument(skip(context))]
+pub async fn ban_from_site(
+ data: Json<BanPerson>,
+ context: Data<LemmyContext>,
+) -> Result<Json<BanPersonResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
-#[async_trait::async_trait(?Send)]
-impl Perform for BanPerson {
- type Response = BanPersonResponse;
+ // Make sure user is an admin
+ is_admin(&local_user_view)?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<BanPersonResponse, LemmyError> {
- let data: &BanPerson = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ is_valid_body_field(&data.reason, false)?;
- // Make sure user is an admin
- is_admin(&local_user_view)?;
+ let expires = data.expires.map(naive_from_unix);
- is_valid_body_field(&data.reason, false)?;
+ let person = Person::update(
+ &mut context.pool(),
+ data.person_id,
+ &PersonUpdateForm::builder()
+ .banned(Some(data.ban))
+ .ban_expires(Some(expires))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
- let ban = data.ban;
- let banned_person_id = data.person_id;
- let expires = data.expires.map(naive_from_unix);
-
- let person = Person::update(
+ // Remove their data if that's desired
+ let remove_data = data.remove_data.unwrap_or(false);
+ if remove_data {
+ remove_user_data(
+ person.id,
&mut context.pool(),
- banned_person_id,
- &PersonUpdateForm::builder()
- .banned(Some(ban))
- .ban_expires(Some(expires))
- .build(),
+ context.settings(),
+ context.client(),
)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?;
+ .await?;
+ }
- // Remove their data if that's desired
- let remove_data = data.remove_data.unwrap_or(false);
- if remove_data {
- remove_user_data(
- person.id,
- &mut context.pool(),
- context.settings(),
- context.client(),
- )
- .await?;
- }
+ // Mod tables
+ let form = ModBanForm {
+ mod_person_id: local_user_view.person.id,
+ other_person_id: data.person_id,
+ reason: sanitize_html_opt(&data.reason),
+ banned: Some(data.ban),
+ expires,
+ };
- // Mod tables
- let form = ModBanForm {
- mod_person_id: local_user_view.person.id,
- other_person_id: data.person_id,
- reason: sanitize_html_opt(&data.reason),
- banned: Some(data.ban),
- expires,
- };
+ ModBan::create(&mut context.pool(), &form).await?;
- ModBan::create(&mut context.pool(), &form).await?;
+ let person_view = PersonView::read(&mut context.pool(), data.person_id).await?;
- let person_id = data.person_id;
- let person_view = PersonView::read(&mut context.pool(), person_id).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::BanFromSite(
+ local_user_view.person,
+ person_view.person.clone(),
+ data.0.clone(),
+ ),
+ &context,
+ )
+ .await?;
- Ok(BanPersonResponse {
- person_view,
- banned: data.ban,
- })
- }
+ Ok(Json(BanPersonResponse {
+ person_view,
+ banned: data.ban,
+ }))
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_post_response,
context::LemmyContext,
post::{FeaturePost, PostResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
};
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl Perform for FeaturePost {
- type Response = PostResponse;
+#[tracing::instrument(skip(context))]
+pub async fn feature_post(
+ data: Json<FeaturePost>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PostResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
- let data: &FeaturePost = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let post_id = data.post_id;
+ let orig_post = Post::read(&mut context.pool(), post_id).await?;
- let post_id = data.post_id;
- let orig_post = Post::read(&mut context.pool(), post_id).await?;
+ check_community_ban(
+ local_user_view.person.id,
+ orig_post.community_id,
+ &mut context.pool(),
+ )
+ .await?;
+ check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
- check_community_ban(
+ if data.feature_type == PostFeatureType::Community {
+ // Verify that only the mods can feature in community
+ is_mod_or_admin(
+ &mut context.pool(),
local_user_view.person.id,
orig_post.community_id,
- &mut context.pool(),
)
.await?;
- check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
+ } else {
+ is_admin(&local_user_view)?;
+ }
- if data.feature_type == PostFeatureType::Community {
- // Verify that only the mods can feature in community
- is_mod_or_admin(
- &mut context.pool(),
- local_user_view.person.id,
- orig_post.community_id,
- )
- .await?;
- } else {
- is_admin(&local_user_view)?;
- }
+ // Update the post
+ let post_id = data.post_id;
+ let new_post: PostUpdateForm = if data.feature_type == PostFeatureType::Community {
+ PostUpdateForm::builder()
+ .featured_community(Some(data.featured))
+ .build()
+ } else {
+ PostUpdateForm::builder()
+ .featured_local(Some(data.featured))
+ .build()
+ };
+ let post = Post::update(&mut context.pool(), post_id, &new_post).await?;
- // Update the post
- let post_id = data.post_id;
- let new_post: PostUpdateForm = if data.feature_type == PostFeatureType::Community {
- PostUpdateForm::builder()
- .featured_community(Some(data.featured))
- .build()
- } else {
- PostUpdateForm::builder()
- .featured_local(Some(data.featured))
- .build()
- };
- Post::update(&mut context.pool(), post_id, &new_post).await?;
+ // Mod tables
+ let form = ModFeaturePostForm {
+ mod_person_id: local_user_view.person.id,
+ post_id: data.post_id,
+ featured: data.featured,
+ is_featured_community: data.feature_type == PostFeatureType::Community,
+ };
- // Mod tables
- let form = ModFeaturePostForm {
- mod_person_id: local_user_view.person.id,
- post_id: data.post_id,
- featured: data.featured,
- is_featured_community: data.feature_type == PostFeatureType::Community,
- };
+ ModFeaturePost::create(&mut context.pool(), &form).await?;
- ModFeaturePost::create(&mut context.pool(), &form).await?;
+ let person_id = local_user_view.person.id;
+ ActivityChannel::submit_activity(
+ SendActivityData::FeaturePost(post, local_user_view.person, data.featured),
+ &context,
+ )
+ .await?;
- build_post_response(
- context,
- orig_post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await
- }
+ build_post_response(&context, orig_post.community_id, person_id, post_id).await
}
)
.await?;
- Ok(Json(
- build_post_response(
- context.deref(),
- post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await?,
- ))
+ build_post_response(
+ context.deref(),
+ post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
-use crate::Perform;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_post_response,
context::LemmyContext,
post::{LockPost, PostResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
check_community_deleted_or_removed,
};
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl Perform for LockPost {
- type Response = PostResponse;
+#[tracing::instrument(skip(context))]
+pub async fn lock_post(
+ data: Json<LockPost>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PostResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
- let data: &LockPost = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let post_id = data.post_id;
+ let orig_post = Post::read(&mut context.pool(), post_id).await?;
- let post_id = data.post_id;
- let orig_post = Post::read(&mut context.pool(), post_id).await?;
+ check_community_ban(
+ local_user_view.person.id,
+ orig_post.community_id,
+ &mut context.pool(),
+ )
+ .await?;
+ check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
- check_community_ban(
- local_user_view.person.id,
- orig_post.community_id,
- &mut context.pool(),
- )
- .await?;
- check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
+ // Verify that only the mods can lock
+ is_mod_or_admin(
+ &mut context.pool(),
+ local_user_view.person.id,
+ orig_post.community_id,
+ )
+ .await?;
- // Verify that only the mods can lock
- is_mod_or_admin(
- &mut context.pool(),
- local_user_view.person.id,
- orig_post.community_id,
- )
- .await?;
+ // Update the post
+ let post_id = data.post_id;
+ let locked = data.locked;
+ let post = Post::update(
+ &mut context.pool(),
+ post_id,
+ &PostUpdateForm::builder().locked(Some(locked)).build(),
+ )
+ .await?;
- // Update the post
- let post_id = data.post_id;
- let locked = data.locked;
- Post::update(
- &mut context.pool(),
- post_id,
- &PostUpdateForm::builder().locked(Some(locked)).build(),
- )
- .await?;
+ // Mod tables
+ let form = ModLockPostForm {
+ mod_person_id: local_user_view.person.id,
+ post_id: data.post_id,
+ locked: Some(locked),
+ };
+ ModLockPost::create(&mut context.pool(), &form).await?;
- // Mod tables
- let form = ModLockPostForm {
- mod_person_id: local_user_view.person.id,
- post_id: data.post_id,
- locked: Some(locked),
- };
- ModLockPost::create(&mut context.pool(), &form).await?;
+ let person_id = local_user_view.person.id;
+ ActivityChannel::submit_activity(
+ SendActivityData::LockPost(post, local_user_view.person, data.locked),
+ &context,
+ )
+ .await?;
- build_post_response(
- context,
- orig_post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await
- }
+ build_post_response(&context, orig_post.community_id, person_id, post_id).await
}
-use crate::{check_report_reason, Perform};
-use actix_web::web::Data;
+use crate::check_report_reason;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
post::{CreatePostReport, PostReportResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_community_ban,
local_user_view_from_jwt,
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
/// Creates a post report and notifies the moderators of the community
-#[async_trait::async_trait(?Send)]
-impl Perform for CreatePostReport {
- type Response = PostReportResponse;
+#[tracing::instrument(skip(context))]
+pub async fn create_post_report(
+ data: Json<CreatePostReport>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PostReportResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostReportResponse, LemmyError> {
- let data: &CreatePostReport = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ let reason = sanitize_html(data.reason.trim());
+ check_report_reason(&reason, &local_site)?;
- let reason = sanitize_html(self.reason.trim());
- check_report_reason(&reason, &local_site)?;
+ let person_id = local_user_view.person.id;
+ let post_id = data.post_id;
+ let post_view = PostView::read(&mut context.pool(), post_id, None, None).await?;
- let person_id = local_user_view.person.id;
- let post_id = data.post_id;
- let post_view = PostView::read(&mut context.pool(), post_id, None, None).await?;
+ check_community_ban(person_id, post_view.community.id, &mut context.pool()).await?;
- check_community_ban(person_id, post_view.community.id, &mut context.pool()).await?;
+ let report_form = PostReportForm {
+ creator_id: person_id,
+ post_id,
+ original_post_name: post_view.post.name,
+ original_post_url: post_view.post.url,
+ original_post_body: post_view.post.body,
+ reason,
+ };
- let report_form = PostReportForm {
- creator_id: person_id,
- post_id,
- original_post_name: post_view.post.name,
- original_post_url: post_view.post.url,
- original_post_body: post_view.post.body,
- reason,
- };
+ let report = PostReport::report(&mut context.pool(), &report_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
- let report = PostReport::report(&mut context.pool(), &report_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntCreateReport)?;
+ let post_report_view = PostReportView::read(&mut context.pool(), report.id, person_id).await?;
- let post_report_view = PostReportView::read(&mut context.pool(), report.id, person_id).await?;
+ // Email the admins
+ if local_site.reports_email_admins {
+ send_new_report_email_to_admins(
+ &post_report_view.creator.name,
+ &post_report_view.post_creator.name,
+ &mut context.pool(),
+ context.settings(),
+ )
+ .await?;
+ }
- // Email the admins
- if local_site.reports_email_admins {
- send_new_report_email_to_admins(
- &post_report_view.creator.name,
- &post_report_view.post_creator.name,
- &mut context.pool(),
- context.settings(),
- )
- .await?;
- }
+ ActivityChannel::submit_activity(
+ SendActivityData::CreateReport(
+ post_view.post.ap_id.inner().clone(),
+ local_user_view.person,
+ post_view.community,
+ data.reason.clone(),
+ ),
+ &context,
+ )
+ .await?;
- Ok(PostReportResponse { post_report_view })
- }
+ Ok(Json(PostReportResponse { post_report_view }))
}
-mod create;
-mod list;
-mod resolve;
+pub mod create;
+pub mod list;
+pub mod resolve;
post::PostResponse,
utils::{check_person_block, get_interface_language, is_mod_or_admin, send_email_to_user},
};
-use actix_web::web::Data;
+use actix_web::web::Json;
use lemmy_db_schema::{
newtypes::{CommentId, CommunityId, LocalUserId, PersonId, PostId},
source::{
}
pub async fn build_community_response(
- context: &Data<LemmyContext>,
+ context: &LemmyContext,
local_user_view: LocalUserView,
community_id: CommunityId,
-) -> Result<CommunityResponse, LemmyError> {
+) -> Result<Json<CommunityResponse>, LemmyError> {
let is_mod_or_admin =
is_mod_or_admin(&mut context.pool(), local_user_view.person.id, community_id)
.await
.await?;
let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?;
- Ok(CommunityResponse {
+ Ok(Json(CommunityResponse {
community_view,
discussion_languages,
- })
+ }))
}
pub async fn build_post_response(
community_id: CommunityId,
person_id: PersonId,
post_id: PostId,
-) -> Result<PostResponse, LemmyError> {
+) -> Result<Json<PostResponse>, LemmyError> {
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person_id, community_id)
.await
.is_ok();
Some(is_mod_or_admin),
)
.await?;
- Ok(PostResponse { post_view })
+ Ok(Json(PostResponse { post_view }))
}
// TODO: this function is a mess and should be split up to handle email seperately
-use crate::context::LemmyContext;
+use crate::{
+ community::BanFromCommunity,
+ context::LemmyContext,
+ person::BanPerson,
+ post::{DeletePost, RemovePost},
+};
use activitypub_federation::config::Data;
use futures::future::BoxFuture;
use lemmy_db_schema::{
- newtypes::DbUrl,
- source::{comment::Comment, community::Community, person::Person, post::Post},
+ newtypes::{CommunityId, DbUrl, PersonId},
+ source::{
+ comment::Comment,
+ community::Community,
+ person::Person,
+ post::Post,
+ private_message::PrivateMessage,
+ },
};
+use lemmy_db_views::structs::PrivateMessageView;
use lemmy_utils::{error::LemmyResult, SYNCHRONOUS_FEDERATION};
use once_cell::sync::{Lazy, OnceCell};
use tokio::{
},
task::JoinHandle,
};
+use url::Url;
type MatchOutgoingActivitiesBoxed =
Box<for<'a> fn(SendActivityData, &'a Data<LemmyContext>) -> BoxFuture<'a, LemmyResult<()>>>;
pub enum SendActivityData {
CreatePost(Post),
UpdatePost(Post),
+ DeletePost(Post, Person, DeletePost),
+ RemovePost(Post, Person, RemovePost),
+ LockPost(Post, Person, bool),
+ FeaturePost(Post, Person, bool),
CreateComment(Comment),
+ UpdateComment(Comment),
DeleteComment(Comment, Person, Community),
RemoveComment(Comment, Person, Community, Option<String>),
- UpdateComment(Comment),
LikePostOrComment(DbUrl, Person, Community, i16),
FollowCommunity(Community, Person, bool),
+ UpdateCommunity(Person, Community),
+ DeleteCommunity(Person, Community, bool),
+ RemoveCommunity(Person, Community, Option<String>, bool),
+ AddModToCommunity(Person, CommunityId, PersonId, bool),
+ BanFromCommunity(Person, CommunityId, Person, BanFromCommunity),
+ BanFromSite(Person, Person, BanPerson),
+ CreatePrivateMessage(PrivateMessageView),
+ UpdatePrivateMessage(PrivateMessageView),
+ DeletePrivateMessage(Person, PrivateMessage, bool),
+ DeleteUser(Person),
+ CreateReport(Url, Person, Community, String),
}
// TODO: instead of static, move this into LemmyContext. make sure that stopping the process with
-use crate::PerformCrud;
-use activitypub_federation::http_signatures::generate_actor_keypair;
-use actix_web::web::Data;
+use activitypub_federation::{config::Data, http_signatures::generate_actor_keypair};
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_community_response,
community::{CommunityResponse, CreateCommunity},
},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for CreateCommunity {
- type Response = CommunityResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
- let data: &CreateCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let site_view = SiteView::read_local(&mut context.pool()).await?;
- let local_site = site_view.local_site;
-
- if local_site.community_creation_admin_only && is_admin(&local_user_view).is_err() {
- return Err(LemmyErrorType::OnlyAdminsCanCreateCommunities)?;
- }
+#[tracing::instrument(skip(context))]
+pub async fn create_community(
+ data: Json<CreateCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
+ let local_site = site_view.local_site;
+
+ if local_site.community_creation_admin_only && is_admin(&local_user_view).is_err() {
+ return Err(LemmyErrorType::OnlyAdminsCanCreateCommunities)?;
+ }
- // Check to make sure the icon and banners are urls
- let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
- let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
-
- let name = sanitize_html(&data.name);
- let title = sanitize_html(&data.title);
- let description = sanitize_html_opt(&data.description);
-
- let slur_regex = local_site_to_slur_regex(&local_site);
- check_slurs(&name, &slur_regex)?;
- check_slurs(&title, &slur_regex)?;
- check_slurs_opt(&description, &slur_regex)?;
-
- is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
- is_valid_body_field(&data.description, false)?;
-
- // Double check for duplicate community actor_ids
- let community_actor_id = generate_local_apub_endpoint(
- EndpointType::Community,
- &data.name,
- &context.settings().get_protocol_and_hostname(),
- )?;
- let community_dupe =
- Community::read_from_apub_id(&mut context.pool(), &community_actor_id).await?;
- if community_dupe.is_some() {
- return Err(LemmyErrorType::CommunityAlreadyExists)?;
- }
+ // Check to make sure the icon and banners are urls
+ let icon = diesel_option_overwrite_to_url_create(&data.icon)?;
+ let banner = diesel_option_overwrite_to_url_create(&data.banner)?;
+
+ let name = sanitize_html(&data.name);
+ let title = sanitize_html(&data.title);
+ let description = sanitize_html_opt(&data.description);
+
+ let slur_regex = local_site_to_slur_regex(&local_site);
+ check_slurs(&name, &slur_regex)?;
+ check_slurs(&title, &slur_regex)?;
+ check_slurs_opt(&description, &slur_regex)?;
+
+ is_valid_actor_name(&data.name, local_site.actor_name_max_length as usize)?;
+ is_valid_body_field(&data.description, false)?;
+
+ // Double check for duplicate community actor_ids
+ let community_actor_id = generate_local_apub_endpoint(
+ EndpointType::Community,
+ &data.name,
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+ let community_dupe =
+ Community::read_from_apub_id(&mut context.pool(), &community_actor_id).await?;
+ if community_dupe.is_some() {
+ return Err(LemmyErrorType::CommunityAlreadyExists)?;
+ }
- // When you create a community, make sure the user becomes a moderator and a follower
- let keypair = generate_actor_keypair()?;
-
- let community_form = CommunityInsertForm::builder()
- .name(name)
- .title(title)
- .description(description)
- .icon(icon)
- .banner(banner)
- .nsfw(data.nsfw)
- .actor_id(Some(community_actor_id.clone()))
- .private_key(Some(keypair.private_key))
- .public_key(keypair.public_key)
- .followers_url(Some(generate_followers_url(&community_actor_id)?))
- .inbox_url(Some(generate_inbox_url(&community_actor_id)?))
- .shared_inbox_url(Some(generate_shared_inbox_url(&community_actor_id)?))
- .posting_restricted_to_mods(data.posting_restricted_to_mods)
- .instance_id(site_view.site.instance_id)
- .build();
-
- let inserted_community = Community::create(&mut context.pool(), &community_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityAlreadyExists)?;
-
- // The community creator becomes a moderator
- let community_moderator_form = CommunityModeratorForm {
- community_id: inserted_community.id,
- person_id: local_user_view.person.id,
- };
-
- CommunityModerator::join(&mut context.pool(), &community_moderator_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
-
- // Follow your own community
- let community_follower_form = CommunityFollowerForm {
- community_id: inserted_community.id,
- person_id: local_user_view.person.id,
- pending: false,
- };
-
- CommunityFollower::follow(&mut context.pool(), &community_follower_form)
- .await
- .with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)?;
-
- // Update the discussion_languages if that's provided
- let community_id = inserted_community.id;
- if let Some(languages) = data.discussion_languages.clone() {
- let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
- // check that community languages are a subset of site languages
- // https://stackoverflow.com/a/64227550
- let is_subset = languages.iter().all(|item| site_languages.contains(item));
- if !is_subset {
- return Err(LemmyErrorType::LanguageNotAllowed)?;
- }
- CommunityLanguage::update(&mut context.pool(), languages, community_id).await?;
+ // When you create a community, make sure the user becomes a moderator and a follower
+ let keypair = generate_actor_keypair()?;
+
+ let community_form = CommunityInsertForm::builder()
+ .name(name)
+ .title(title)
+ .description(description)
+ .icon(icon)
+ .banner(banner)
+ .nsfw(data.nsfw)
+ .actor_id(Some(community_actor_id.clone()))
+ .private_key(Some(keypair.private_key))
+ .public_key(keypair.public_key)
+ .followers_url(Some(generate_followers_url(&community_actor_id)?))
+ .inbox_url(Some(generate_inbox_url(&community_actor_id)?))
+ .shared_inbox_url(Some(generate_shared_inbox_url(&community_actor_id)?))
+ .posting_restricted_to_mods(data.posting_restricted_to_mods)
+ .instance_id(site_view.site.instance_id)
+ .build();
+
+ let inserted_community = Community::create(&mut context.pool(), &community_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityAlreadyExists)?;
+
+ // The community creator becomes a moderator
+ let community_moderator_form = CommunityModeratorForm {
+ community_id: inserted_community.id,
+ person_id: local_user_view.person.id,
+ };
+
+ CommunityModerator::join(&mut context.pool(), &community_moderator_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityModeratorAlreadyExists)?;
+
+ // Follow your own community
+ let community_follower_form = CommunityFollowerForm {
+ community_id: inserted_community.id,
+ person_id: local_user_view.person.id,
+ pending: false,
+ };
+
+ CommunityFollower::follow(&mut context.pool(), &community_follower_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CommunityFollowerAlreadyExists)?;
+
+ // Update the discussion_languages if that's provided
+ let community_id = inserted_community.id;
+ if let Some(languages) = data.discussion_languages.clone() {
+ let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
+ // check that community languages are a subset of site languages
+ // https://stackoverflow.com/a/64227550
+ let is_subset = languages.iter().all(|item| site_languages.contains(item));
+ if !is_subset {
+ return Err(LemmyErrorType::LanguageNotAllowed)?;
}
-
- build_community_response(context, local_user_view, community_id).await
+ CommunityLanguage::update(&mut context.pool(), languages, community_id).await?;
}
+
+ build_community_response(&context, local_user_view, community_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_community_response,
community::{CommunityResponse, DeleteCommunity},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{is_top_mod, local_user_view_from_jwt},
};
use lemmy_db_schema::{
use lemmy_db_views_actor::structs::CommunityModeratorView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for DeleteCommunity {
- type Response = CommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn delete_community(
+ data: Json<DeleteCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
- let data: &DeleteCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ // Fetch the community mods
+ let community_id = data.community_id;
+ let community_mods =
+ CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
- // Fetch the community mods
- let community_id = data.community_id;
- let community_mods =
- CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
+ // Make sure deleter is the top mod
+ is_top_mod(&local_user_view, &community_mods)?;
- // Make sure deleter is the top mod
- is_top_mod(&local_user_view, &community_mods)?;
+ // Do the delete
+ let community_id = data.community_id;
+ let deleted = data.deleted;
+ let community = Community::update(
+ &mut context.pool(),
+ community_id,
+ &CommunityUpdateForm::builder()
+ .deleted(Some(deleted))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
- // Do the delete
- let community_id = data.community_id;
- let deleted = data.deleted;
- Community::update(
- &mut context.pool(),
- community_id,
- &CommunityUpdateForm::builder()
- .deleted(Some(deleted))
- .build(),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
+ ActivityChannel::submit_activity(
+ SendActivityData::DeleteCommunity(local_user_view.person.clone(), community, data.deleted),
+ &context,
+ )
+ .await?;
- build_community_response(context, local_user_view, community_id).await
- }
+ build_community_response(&context, local_user_view, community_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_community_response,
community::{CommunityResponse, RemoveCommunity},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{is_admin, local_user_view_from_jwt},
};
use lemmy_db_schema::{
utils::time::naive_from_unix,
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for RemoveCommunity {
- type Response = CommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn remove_community(
+ data: Json<RemoveCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
- let data: &RemoveCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ // Verify its an admin (only an admin can remove a community)
+ is_admin(&local_user_view)?;
- // Verify its an admin (only an admin can remove a community)
- is_admin(&local_user_view)?;
+ // Do the remove
+ let community_id = data.community_id;
+ let removed = data.removed;
+ let community = Community::update(
+ &mut context.pool(),
+ community_id,
+ &CommunityUpdateForm::builder()
+ .removed(Some(removed))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
- // Do the remove
- let community_id = data.community_id;
- let removed = data.removed;
- Community::update(
- &mut context.pool(),
- community_id,
- &CommunityUpdateForm::builder()
- .removed(Some(removed))
- .build(),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
+ // Mod tables
+ let expires = data.expires.map(naive_from_unix);
+ let form = ModRemoveCommunityForm {
+ mod_person_id: local_user_view.person.id,
+ community_id: data.community_id,
+ removed: Some(removed),
+ reason: data.reason.clone(),
+ expires,
+ };
+ ModRemoveCommunity::create(&mut context.pool(), &form).await?;
- // Mod tables
- let expires = data.expires.map(naive_from_unix);
- let form = ModRemoveCommunityForm {
- mod_person_id: local_user_view.person.id,
- community_id: data.community_id,
- removed: Some(removed),
- reason: data.reason.clone(),
- expires,
- };
- ModRemoveCommunity::create(&mut context.pool(), &form).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::RemoveCommunity(
+ local_user_view.person.clone(),
+ community,
+ data.reason.clone(),
+ data.removed,
+ ),
+ &context,
+ )
+ .await?;
- build_community_response(context, local_user_view, community_id).await
- }
+ build_community_response(&context, local_user_view, community_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_community_response,
community::{CommunityResponse, EditCommunity},
context::LemmyContext,
+ send_activity::{ActivityChannel, SendActivityData},
utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html_opt},
};
use lemmy_db_schema::{
utils::{slurs::check_slurs_opt, validation::is_valid_body_field},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for EditCommunity {
- type Response = CommunityResponse;
+#[tracing::instrument(skip(context))]
+pub async fn update_community(
+ data: Json<EditCommunity>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CommunityResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
- let data: &EditCommunity = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ let slur_regex = local_site_to_slur_regex(&local_site);
+ check_slurs_opt(&data.title, &slur_regex)?;
+ check_slurs_opt(&data.description, &slur_regex)?;
+ is_valid_body_field(&data.description, false)?;
- let slur_regex = local_site_to_slur_regex(&local_site);
- check_slurs_opt(&data.title, &slur_regex)?;
- check_slurs_opt(&data.description, &slur_regex)?;
- is_valid_body_field(&data.description, false)?;
+ let title = sanitize_html_opt(&data.title);
+ let description = sanitize_html_opt(&data.description);
- let title = sanitize_html_opt(&data.title);
- let description = sanitize_html_opt(&data.description);
+ let icon = diesel_option_overwrite_to_url(&data.icon)?;
+ let banner = diesel_option_overwrite_to_url(&data.banner)?;
+ let description = diesel_option_overwrite(description);
- let icon = diesel_option_overwrite_to_url(&data.icon)?;
- let banner = diesel_option_overwrite_to_url(&data.banner)?;
- let description = diesel_option_overwrite(description);
+ // Verify its a mod (only mods can edit it)
+ let community_id = data.community_id;
+ let mods: Vec<PersonId> =
+ CommunityModeratorView::for_community(&mut context.pool(), community_id)
+ .await
+ .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?;
+ if !mods.contains(&local_user_view.person.id) {
+ return Err(LemmyErrorType::NotAModerator)?;
+ }
- // Verify its a mod (only mods can edit it)
- let community_id = data.community_id;
- let mods: Vec<PersonId> =
- CommunityModeratorView::for_community(&mut context.pool(), community_id)
- .await
- .map(|v| v.into_iter().map(|m| m.moderator.id).collect())?;
- if !mods.contains(&local_user_view.person.id) {
- return Err(LemmyErrorType::NotAModerator)?;
+ let community_id = data.community_id;
+ if let Some(languages) = data.discussion_languages.clone() {
+ let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
+ // check that community languages are a subset of site languages
+ // https://stackoverflow.com/a/64227550
+ let is_subset = languages.iter().all(|item| site_languages.contains(item));
+ if !is_subset {
+ return Err(LemmyErrorType::LanguageNotAllowed)?;
}
+ CommunityLanguage::update(&mut context.pool(), languages, community_id).await?;
+ }
- let community_id = data.community_id;
- if let Some(languages) = data.discussion_languages.clone() {
- let site_languages = SiteLanguage::read_local_raw(&mut context.pool()).await?;
- // check that community languages are a subset of site languages
- // https://stackoverflow.com/a/64227550
- let is_subset = languages.iter().all(|item| site_languages.contains(item));
- if !is_subset {
- return Err(LemmyErrorType::LanguageNotAllowed)?;
- }
- CommunityLanguage::update(&mut context.pool(), languages, community_id).await?;
- }
+ let community_form = CommunityUpdateForm::builder()
+ .title(title)
+ .description(description)
+ .icon(icon)
+ .banner(banner)
+ .nsfw(data.nsfw)
+ .posting_restricted_to_mods(data.posting_restricted_to_mods)
+ .updated(Some(Some(naive_now())))
+ .build();
- let community_form = CommunityUpdateForm::builder()
- .title(title)
- .description(description)
- .icon(icon)
- .banner(banner)
- .nsfw(data.nsfw)
- .posting_restricted_to_mods(data.posting_restricted_to_mods)
- .updated(Some(Some(naive_now())))
- .build();
+ let community_id = data.community_id;
+ let community = Community::update(&mut context.pool(), community_id, &community_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
- let community_id = data.community_id;
- Community::update(&mut context.pool(), community_id, &community_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
+ ActivityChannel::submit_activity(
+ SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
+ &context,
+ )
+ .await?;
- build_community_response(context, local_user_view, community_id).await
- }
+ build_community_response(&context, local_user_view, community_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
custom_emoji::{CreateCustomEmoji, CustomEmojiResponse},
use lemmy_db_views::structs::CustomEmojiView;
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for CreateCustomEmoji {
- type Response = CustomEmojiResponse;
+#[tracing::instrument(skip(context))]
+pub async fn create_custom_emoji(
+ data: Json<CreateCustomEmoji>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CustomEmojiResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CustomEmojiResponse, LemmyError> {
- let data: &CreateCustomEmoji = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
+ // Make sure user is an admin
+ is_admin(&local_user_view)?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
- // Make sure user is an admin
- is_admin(&local_user_view)?;
+ let shortcode = sanitize_html(data.shortcode.to_lowercase().trim());
+ let alt_text = sanitize_html(&data.alt_text);
+ let category = sanitize_html(&data.category);
- let shortcode = sanitize_html(data.shortcode.to_lowercase().trim());
- let alt_text = sanitize_html(&data.alt_text);
- let category = sanitize_html(&data.category);
-
- let emoji_form = CustomEmojiInsertForm::builder()
- .local_site_id(local_site.id)
- .shortcode(shortcode)
- .alt_text(alt_text)
- .category(category)
- .image_url(data.clone().image_url.into())
+ let emoji_form = CustomEmojiInsertForm::builder()
+ .local_site_id(local_site.id)
+ .shortcode(shortcode)
+ .alt_text(alt_text)
+ .category(category)
+ .image_url(data.clone().image_url.into())
+ .build();
+ let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
+ let mut keywords = vec![];
+ for keyword in &data.keywords {
+ let keyword_form = CustomEmojiKeywordInsertForm::builder()
+ .custom_emoji_id(emoji.id)
+ .keyword(keyword.to_lowercase().trim().to_string())
.build();
- let emoji = CustomEmoji::create(&mut context.pool(), &emoji_form).await?;
- let mut keywords = vec![];
- for keyword in &data.keywords {
- let keyword_form = CustomEmojiKeywordInsertForm::builder()
- .custom_emoji_id(emoji.id)
- .keyword(keyword.to_lowercase().trim().to_string())
- .build();
- keywords.push(keyword_form);
- }
- CustomEmojiKeyword::create(&mut context.pool(), keywords).await?;
- let view = CustomEmojiView::get(&mut context.pool(), emoji.id).await?;
- Ok(CustomEmojiResponse { custom_emoji: view })
+ keywords.push(keyword_form);
}
+ CustomEmojiKeyword::create(&mut context.pool(), keywords).await?;
+ let view = CustomEmojiView::get(&mut context.pool(), emoji.id).await?;
+ Ok(Json(CustomEmojiResponse { custom_emoji: view }))
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
custom_emoji::{DeleteCustomEmoji, DeleteCustomEmojiResponse},
use lemmy_db_schema::source::custom_emoji::CustomEmoji;
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for DeleteCustomEmoji {
- type Response = DeleteCustomEmojiResponse;
+#[tracing::instrument(skip(context))]
+pub async fn delete_custom_emoji(
+ data: Json<DeleteCustomEmoji>,
+ context: Data<LemmyContext>,
+) -> Result<Json<DeleteCustomEmojiResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<DeleteCustomEmojiResponse, LemmyError> {
- let data: &DeleteCustomEmoji = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
-
- // Make sure user is an admin
- is_admin(&local_user_view)?;
- CustomEmoji::delete(&mut context.pool(), data.id).await?;
- Ok(DeleteCustomEmojiResponse {
- id: data.id,
- success: true,
- })
- }
+ // Make sure user is an admin
+ is_admin(&local_user_view)?;
+ CustomEmoji::delete(&mut context.pool(), data.id).await?;
+ Ok(Json(DeleteCustomEmojiResponse {
+ id: data.id,
+ success: true,
+ }))
}
-mod create;
-mod delete;
-mod update;
+pub mod create;
+pub mod delete;
+pub mod update;
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
custom_emoji::{CustomEmojiResponse, EditCustomEmoji},
use lemmy_db_views::structs::CustomEmojiView;
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for EditCustomEmoji {
- type Response = CustomEmojiResponse;
+#[tracing::instrument(skip(context))]
+pub async fn update_custom_emoji(
+ data: Json<EditCustomEmoji>,
+ context: Data<LemmyContext>,
+) -> Result<Json<CustomEmojiResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<CustomEmojiResponse, LemmyError> {
- let data: &EditCustomEmoji = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
+ // Make sure user is an admin
+ is_admin(&local_user_view)?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
- // Make sure user is an admin
- is_admin(&local_user_view)?;
+ let alt_text = sanitize_html(&data.alt_text);
+ let category = sanitize_html(&data.category);
- let alt_text = sanitize_html(&data.alt_text);
- let category = sanitize_html(&data.category);
-
- let emoji_form = CustomEmojiUpdateForm::builder()
- .local_site_id(local_site.id)
- .alt_text(alt_text)
- .category(category)
- .image_url(data.clone().image_url.into())
+ let emoji_form = CustomEmojiUpdateForm::builder()
+ .local_site_id(local_site.id)
+ .alt_text(alt_text)
+ .category(category)
+ .image_url(data.clone().image_url.into())
+ .build();
+ let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
+ CustomEmojiKeyword::delete(&mut context.pool(), data.id).await?;
+ let mut keywords = vec![];
+ for keyword in &data.keywords {
+ let keyword_form = CustomEmojiKeywordInsertForm::builder()
+ .custom_emoji_id(emoji.id)
+ .keyword(keyword.to_lowercase().trim().to_string())
.build();
- let emoji = CustomEmoji::update(&mut context.pool(), data.id, &emoji_form).await?;
- CustomEmojiKeyword::delete(&mut context.pool(), data.id).await?;
- let mut keywords = vec![];
- for keyword in &data.keywords {
- let keyword_form = CustomEmojiKeywordInsertForm::builder()
- .custom_emoji_id(emoji.id)
- .keyword(keyword.to_lowercase().trim().to_string())
- .build();
- keywords.push(keyword_form);
- }
- CustomEmojiKeyword::create(&mut context.pool(), keywords).await?;
- let view = CustomEmojiView::get(&mut context.pool(), emoji.id).await?;
- Ok(CustomEmojiResponse { custom_emoji: view })
+ keywords.push(keyword_form);
}
+ CustomEmojiKeyword::create(&mut context.pool(), keywords).await?;
+ let view = CustomEmojiView::get(&mut context.pool(), emoji.id).await?;
+ Ok(Json(CustomEmojiResponse { custom_emoji: view }))
}
-use actix_web::web::Data;
-use lemmy_api_common::context::LemmyContext;
-use lemmy_utils::error::LemmyError;
-
pub mod comment;
pub mod community;
pub mod custom_emoji;
pub mod private_message;
pub mod site;
pub mod user;
-
-#[async_trait::async_trait(?Send)]
-pub trait PerformCrud {
- type Response: serde::ser::Serialize + Send + Clone + Sync;
-
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError>;
-}
}
};
- Ok(Json(
- build_post_response(&context, community_id, person_id, post_id).await?,
- ))
+ build_post_response(&context, community_id, person_id, post_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_post_response,
context::LemmyContext,
post::{DeletePost, PostResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, check_community_deleted_or_removed, local_user_view_from_jwt},
};
use lemmy_db_schema::{
};
use lemmy_utils::error::{LemmyError, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for DeletePost {
- type Response = PostResponse;
-
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
- let data: &DeletePost = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
-
- let post_id = data.post_id;
- let orig_post = Post::read(&mut context.pool(), post_id).await?;
-
- // Dont delete it if its already been deleted.
- if orig_post.deleted == data.deleted {
- return Err(LemmyErrorType::CouldntUpdatePost)?;
- }
-
- check_community_ban(
- local_user_view.person.id,
- orig_post.community_id,
- &mut context.pool(),
- )
- .await?;
- check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
-
- // Verify that only the creator can delete
- if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
- return Err(LemmyErrorType::NoPostEditAllowed)?;
- }
-
- // Update the post
- let post_id = data.post_id;
- let deleted = data.deleted;
- Post::update(
- &mut context.pool(),
- post_id,
- &PostUpdateForm::builder().deleted(Some(deleted)).build(),
- )
- .await?;
-
- build_post_response(
- context,
- orig_post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await
+#[tracing::instrument(skip(context))]
+pub async fn delete_post(
+ data: Json<DeletePost>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PostResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+
+ let post_id = data.post_id;
+ let orig_post = Post::read(&mut context.pool(), post_id).await?;
+
+ // Dont delete it if its already been deleted.
+ if orig_post.deleted == data.deleted {
+ return Err(LemmyErrorType::CouldntUpdatePost)?;
}
+
+ check_community_ban(
+ local_user_view.person.id,
+ orig_post.community_id,
+ &mut context.pool(),
+ )
+ .await?;
+ check_community_deleted_or_removed(orig_post.community_id, &mut context.pool()).await?;
+
+ // Verify that only the creator can delete
+ if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
+ return Err(LemmyErrorType::NoPostEditAllowed)?;
+ }
+
+ // Update the post
+ let post = Post::update(
+ &mut context.pool(),
+ data.post_id,
+ &PostUpdateForm::builder()
+ .deleted(Some(data.deleted))
+ .build(),
+ )
+ .await?;
+
+ let person_id = local_user_view.person.id;
+ ActivityChannel::submit_activity(
+ SendActivityData::DeletePost(post, local_user_view.person, data.0.clone()),
+ &context,
+ )
+ .await?;
+
+ build_post_response(&context, orig_post.community_id, person_id, data.post_id).await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
build_response::build_post_response,
context::LemmyContext,
post::{PostResponse, RemovePost},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{check_community_ban, is_mod_or_admin, local_user_view_from_jwt},
};
use lemmy_db_schema::{
};
use lemmy_utils::error::LemmyError;
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for RemovePost {
- type Response = PostResponse;
+#[tracing::instrument(skip(context))]
+pub async fn remove_post(
+ data: Json<RemovePost>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PostResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<PostResponse, LemmyError> {
- let data: &RemovePost = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ let post_id = data.post_id;
+ let orig_post = Post::read(&mut context.pool(), post_id).await?;
- let post_id = data.post_id;
- let orig_post = Post::read(&mut context.pool(), post_id).await?;
+ check_community_ban(
+ local_user_view.person.id,
+ orig_post.community_id,
+ &mut context.pool(),
+ )
+ .await?;
- check_community_ban(
- local_user_view.person.id,
- orig_post.community_id,
- &mut context.pool(),
- )
- .await?;
+ // Verify that only the mods can remove
+ is_mod_or_admin(
+ &mut context.pool(),
+ local_user_view.person.id,
+ orig_post.community_id,
+ )
+ .await?;
- // Verify that only the mods can remove
- is_mod_or_admin(
- &mut context.pool(),
- local_user_view.person.id,
- orig_post.community_id,
- )
- .await?;
+ // Update the post
+ let post_id = data.post_id;
+ let removed = data.removed;
+ let post = Post::update(
+ &mut context.pool(),
+ post_id,
+ &PostUpdateForm::builder().removed(Some(removed)).build(),
+ )
+ .await?;
- // Update the post
- let post_id = data.post_id;
- let removed = data.removed;
- Post::update(
- &mut context.pool(),
- post_id,
- &PostUpdateForm::builder().removed(Some(removed)).build(),
- )
- .await?;
+ // Mod tables
+ let form = ModRemovePostForm {
+ mod_person_id: local_user_view.person.id,
+ post_id: data.post_id,
+ removed: Some(removed),
+ reason: data.reason.clone(),
+ };
+ ModRemovePost::create(&mut context.pool(), &form).await?;
- // Mod tables
- let form = ModRemovePostForm {
- mod_person_id: local_user_view.person.id,
- post_id: data.post_id,
- removed: Some(removed),
- reason: data.reason.clone(),
- };
- ModRemovePost::create(&mut context.pool(), &form).await?;
+ let person_id = local_user_view.person.id;
+ ActivityChannel::submit_activity(
+ SendActivityData::RemovePost(post, local_user_view.person, data.0),
+ &context,
+ )
+ .await?;
- build_post_response(
- context,
- orig_post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await
- }
+ build_post_response(&context, orig_post.community_id, person_id, post_id).await
}
ActivityChannel::submit_activity(SendActivityData::UpdatePost(updated_post), &context).await?;
- Ok(Json(
- build_post_response(
- context.deref(),
- orig_post.community_id,
- local_user_view.person.id,
- post_id,
- )
- .await?,
- ))
+ build_post_response(
+ context.deref(),
+ orig_post.community_id,
+ local_user_view.person.id,
+ post_id,
+ )
+ .await
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
private_message::{CreatePrivateMessage, PrivateMessageResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{
check_person_block,
generate_local_apub_endpoint,
utils::{slurs::remove_slurs, validation::is_valid_body_field},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for CreatePrivateMessage {
- type Response = PrivateMessageResponse;
+#[tracing::instrument(skip(context))]
+pub async fn create_private_message(
+ data: Json<CreatePrivateMessage>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PrivateMessageResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<PrivateMessageResponse, LemmyError> {
- let data: &CreatePrivateMessage = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ let content = sanitize_html(&data.content);
+ let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
+ is_valid_body_field(&Some(content.clone()), false)?;
- let content = sanitize_html(&data.content);
- let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
- is_valid_body_field(&Some(content.clone()), false)?;
+ check_person_block(
+ local_user_view.person.id,
+ data.recipient_id,
+ &mut context.pool(),
+ )
+ .await?;
- check_person_block(
- local_user_view.person.id,
- data.recipient_id,
- &mut context.pool(),
- )
- .await?;
-
- let private_message_form = PrivateMessageInsertForm::builder()
- .content(content.clone())
- .creator_id(local_user_view.person.id)
- .recipient_id(data.recipient_id)
- .build();
+ let private_message_form = PrivateMessageInsertForm::builder()
+ .content(content.clone())
+ .creator_id(local_user_view.person.id)
+ .recipient_id(data.recipient_id)
+ .build();
- let inserted_private_message =
- PrivateMessage::create(&mut context.pool(), &private_message_form)
- .await
- .with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?;
-
- let inserted_private_message_id = inserted_private_message.id;
- let protocol_and_hostname = context.settings().get_protocol_and_hostname();
- let apub_id = generate_local_apub_endpoint(
- EndpointType::PrivateMessage,
- &inserted_private_message_id.to_string(),
- &protocol_and_hostname,
- )?;
- PrivateMessage::update(
- &mut context.pool(),
- inserted_private_message.id,
- &PrivateMessageUpdateForm::builder()
- .ap_id(Some(apub_id))
- .build(),
- )
+ let inserted_private_message = PrivateMessage::create(&mut context.pool(), &private_message_form)
.await
.with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?;
- let view = PrivateMessageView::read(&mut context.pool(), inserted_private_message.id).await?;
+ let inserted_private_message_id = inserted_private_message.id;
+ let protocol_and_hostname = context.settings().get_protocol_and_hostname();
+ let apub_id = generate_local_apub_endpoint(
+ EndpointType::PrivateMessage,
+ &inserted_private_message_id.to_string(),
+ &protocol_and_hostname,
+ )?;
+ PrivateMessage::update(
+ &mut context.pool(),
+ inserted_private_message.id,
+ &PrivateMessageUpdateForm::builder()
+ .ap_id(Some(apub_id))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?;
- // Send email to the local recipient, if one exists
- if view.recipient.local {
- let recipient_id = data.recipient_id;
- let local_recipient = LocalUserView::read_person(&mut context.pool(), recipient_id).await?;
- let lang = get_interface_language(&local_recipient);
- let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
- let sender_name = &local_user_view.person.name;
- send_email_to_user(
- &local_recipient,
- &lang.notification_private_message_subject(sender_name),
- &lang.notification_private_message_body(inbox_link, &content, sender_name),
- context.settings(),
- )
- .await;
- }
+ let view = PrivateMessageView::read(&mut context.pool(), inserted_private_message.id).await?;
- Ok(PrivateMessageResponse {
- private_message_view: view,
- })
+ // Send email to the local recipient, if one exists
+ if view.recipient.local {
+ let recipient_id = data.recipient_id;
+ let local_recipient = LocalUserView::read_person(&mut context.pool(), recipient_id).await?;
+ let lang = get_interface_language(&local_recipient);
+ let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
+ let sender_name = &local_user_view.person.name;
+ send_email_to_user(
+ &local_recipient,
+ &lang.notification_private_message_subject(sender_name),
+ &lang.notification_private_message_body(inbox_link, &content, sender_name),
+ context.settings(),
+ )
+ .await;
}
+
+ ActivityChannel::submit_activity(
+ SendActivityData::CreatePrivateMessage(view.clone()),
+ &context,
+ )
+ .await?;
+
+ Ok(Json(PrivateMessageResponse {
+ private_message_view: view,
+ }))
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
private_message::{DeletePrivateMessage, PrivateMessageResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::local_user_view_from_jwt,
};
use lemmy_db_schema::{
use lemmy_db_views::structs::PrivateMessageView;
use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for DeletePrivateMessage {
- type Response = PrivateMessageResponse;
+#[tracing::instrument(skip(context))]
+pub async fn delete_private_message(
+ data: Json<DeletePrivateMessage>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PrivateMessageResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<PrivateMessageResponse, LemmyError> {
- let data: &DeletePrivateMessage = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
+ // Checking permissions
+ let private_message_id = data.private_message_id;
+ let orig_private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?;
+ if local_user_view.person.id != orig_private_message.creator_id {
+ return Err(LemmyErrorType::EditPrivateMessageNotAllowed)?;
+ }
- // Checking permissions
- let private_message_id = data.private_message_id;
- let orig_private_message =
- PrivateMessage::read(&mut context.pool(), private_message_id).await?;
- if local_user_view.person.id != orig_private_message.creator_id {
- return Err(LemmyErrorType::EditPrivateMessageNotAllowed)?;
- }
+ // Doing the update
+ let private_message_id = data.private_message_id;
+ let deleted = data.deleted;
+ let private_message = PrivateMessage::update(
+ &mut context.pool(),
+ private_message_id,
+ &PrivateMessageUpdateForm::builder()
+ .deleted(Some(deleted))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
- // Doing the update
- let private_message_id = data.private_message_id;
- let deleted = data.deleted;
- PrivateMessage::update(
- &mut context.pool(),
- private_message_id,
- &PrivateMessageUpdateForm::builder()
- .deleted(Some(deleted))
- .build(),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
+ ActivityChannel::submit_activity(
+ SendActivityData::DeletePrivateMessage(local_user_view.person, private_message, data.deleted),
+ &context,
+ )
+ .await?;
- let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
- Ok(PrivateMessageResponse {
- private_message_view: view,
- })
- }
+ let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
+ Ok(Json(PrivateMessageResponse {
+ private_message_view: view,
+ }))
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
private_message::{EditPrivateMessage, PrivateMessageResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::{local_site_to_slur_regex, local_user_view_from_jwt, sanitize_html},
};
use lemmy_db_schema::{
utils::{slurs::remove_slurs, validation::is_valid_body_field},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for EditPrivateMessage {
- type Response = PrivateMessageResponse;
+#[tracing::instrument(skip(context))]
+pub async fn update_private_message(
+ data: Json<EditPrivateMessage>,
+ context: Data<LemmyContext>,
+) -> Result<Json<PrivateMessageResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?;
+ let local_site = LocalSite::read(&mut context.pool()).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(
- &self,
- context: &Data<LemmyContext>,
- ) -> Result<PrivateMessageResponse, LemmyError> {
- let data: &EditPrivateMessage = self;
- let local_user_view = local_user_view_from_jwt(&data.auth, context).await?;
- let local_site = LocalSite::read(&mut context.pool()).await?;
+ // Checking permissions
+ let private_message_id = data.private_message_id;
+ let orig_private_message = PrivateMessage::read(&mut context.pool(), private_message_id).await?;
+ if local_user_view.person.id != orig_private_message.creator_id {
+ return Err(LemmyErrorType::EditPrivateMessageNotAllowed)?;
+ }
- // Checking permissions
- let private_message_id = data.private_message_id;
- let orig_private_message =
- PrivateMessage::read(&mut context.pool(), private_message_id).await?;
- if local_user_view.person.id != orig_private_message.creator_id {
- return Err(LemmyErrorType::EditPrivateMessageNotAllowed)?;
- }
+ // Doing the update
+ let content = sanitize_html(&data.content);
+ let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
+ is_valid_body_field(&Some(content.clone()), false)?;
- // Doing the update
- let content = sanitize_html(&data.content);
- let content = remove_slurs(&content, &local_site_to_slur_regex(&local_site));
- is_valid_body_field(&Some(content.clone()), false)?;
+ let private_message_id = data.private_message_id;
+ PrivateMessage::update(
+ &mut context.pool(),
+ private_message_id,
+ &PrivateMessageUpdateForm::builder()
+ .content(Some(content))
+ .updated(Some(Some(naive_now())))
+ .build(),
+ )
+ .await
+ .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
- let private_message_id = data.private_message_id;
- PrivateMessage::update(
- &mut context.pool(),
- private_message_id,
- &PrivateMessageUpdateForm::builder()
- .content(Some(content))
- .updated(Some(Some(naive_now())))
- .build(),
- )
- .await
- .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?;
+ let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
- let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
+ ActivityChannel::submit_activity(
+ SendActivityData::UpdatePrivateMessage(view.clone()),
+ &context,
+ )
+ .await?;
- Ok(PrivateMessageResponse {
- private_message_view: view,
- })
- }
+ Ok(Json(PrivateMessageResponse {
+ private_message_view: view,
+ }))
}
-use crate::PerformCrud;
-use activitypub_federation::http_signatures::generate_actor_keypair;
-use actix_web::web::Data;
+use activitypub_federation::{config::Data, http_signatures::generate_actor_keypair};
+use actix_web::web::Json;
use lemmy_api_common::{
context::LemmyContext,
person::{LoginResponse, Register},
},
};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for Register {
- type Response = LoginResponse;
-
- #[tracing::instrument(skip(self, context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
- let data: &Register = self;
-
- let site_view = SiteView::read_local(&mut context.pool()).await?;
- let local_site = site_view.local_site;
- let require_registration_application =
- local_site.registration_mode == RegistrationMode::RequireApplication;
-
- if local_site.registration_mode == RegistrationMode::Closed {
- return Err(LemmyErrorType::RegistrationClosed)?;
- }
+#[tracing::instrument(skip(context))]
+pub async fn register(
+ data: Json<Register>,
+ context: Data<LemmyContext>,
+) -> Result<Json<LoginResponse>, LemmyError> {
+ let site_view = SiteView::read_local(&mut context.pool()).await?;
+ let local_site = site_view.local_site;
+ let require_registration_application =
+ local_site.registration_mode == RegistrationMode::RequireApplication;
+
+ if local_site.registration_mode == RegistrationMode::Closed {
+ return Err(LemmyErrorType::RegistrationClosed)?;
+ }
- password_length_check(&data.password)?;
- honeypot_check(&data.honeypot)?;
+ password_length_check(&data.password)?;
+ honeypot_check(&data.honeypot)?;
- if local_site.require_email_verification && data.email.is_none() {
- return Err(LemmyErrorType::EmailRequired)?;
- }
+ if local_site.require_email_verification && data.email.is_none() {
+ return Err(LemmyErrorType::EmailRequired)?;
+ }
- if local_site.site_setup && require_registration_application && data.answer.is_none() {
- return Err(LemmyErrorType::RegistrationApplicationAnswerRequired)?;
- }
+ if local_site.site_setup && require_registration_application && data.answer.is_none() {
+ return Err(LemmyErrorType::RegistrationApplicationAnswerRequired)?;
+ }
- // Make sure passwords match
- if data.password != data.password_verify {
- return Err(LemmyErrorType::PasswordsDoNotMatch)?;
- }
+ // Make sure passwords match
+ if data.password != data.password_verify {
+ return Err(LemmyErrorType::PasswordsDoNotMatch)?;
+ }
- if local_site.site_setup && local_site.captcha_enabled {
- if let Some(captcha_uuid) = &data.captcha_uuid {
- let uuid = uuid::Uuid::parse_str(captcha_uuid)?;
- let check = CaptchaAnswer::check_captcha(
- &mut context.pool(),
- CheckCaptchaAnswer {
- uuid,
- answer: data.captcha_answer.clone().unwrap_or_default(),
- },
- )
- .await?;
- if !check {
- return Err(LemmyErrorType::CaptchaIncorrect)?;
- }
- } else {
+ if local_site.site_setup && local_site.captcha_enabled {
+ if let Some(captcha_uuid) = &data.captcha_uuid {
+ let uuid = uuid::Uuid::parse_str(captcha_uuid)?;
+ let check = CaptchaAnswer::check_captcha(
+ &mut context.pool(),
+ CheckCaptchaAnswer {
+ uuid,
+ answer: data.captcha_answer.clone().unwrap_or_default(),
+ },
+ )
+ .await?;
+ if !check {
return Err(LemmyErrorType::CaptchaIncorrect)?;
}
+ } else {
+ return Err(LemmyErrorType::CaptchaIncorrect)?;
}
+ }
- let slur_regex = local_site_to_slur_regex(&local_site);
- check_slurs(&data.username, &slur_regex)?;
- check_slurs_opt(&data.answer, &slur_regex)?;
- let username = sanitize_html(&data.username);
-
- let actor_keypair = generate_actor_keypair()?;
- is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
- let actor_id = generate_local_apub_endpoint(
- EndpointType::Person,
- &data.username,
- &context.settings().get_protocol_and_hostname(),
- )?;
-
- if let Some(email) = &data.email {
- if LocalUser::is_email_taken(&mut context.pool(), email).await? {
- return Err(LemmyErrorType::EmailAlreadyExists)?;
- }
- }
-
- // We have to create both a person, and local_user
-
- // Register the new person
- let person_form = PersonInsertForm::builder()
- .name(username)
- .actor_id(Some(actor_id.clone()))
- .private_key(Some(actor_keypair.private_key))
- .public_key(actor_keypair.public_key)
- .inbox_url(Some(generate_inbox_url(&actor_id)?))
- .shared_inbox_url(Some(generate_shared_inbox_url(&actor_id)?))
- // If its the initial site setup, they are an admin
- .admin(Some(!local_site.site_setup))
- .instance_id(site_view.site.instance_id)
- .build();
-
- // insert the person
- let inserted_person = Person::create(&mut context.pool(), &person_form)
- .await
- .with_lemmy_type(LemmyErrorType::UserAlreadyExists)?;
-
- // Automatically set their application as accepted, if they created this with open registration.
- // Also fixes a bug which allows users to log in when registrations are changed to closed.
- let accepted_application = Some(!require_registration_application);
-
- // Create the local user
- let local_user_form = LocalUserInsertForm::builder()
- .person_id(inserted_person.id)
- .email(data.email.as_deref().map(str::to_lowercase))
- .password_encrypted(data.password.to_string())
- .show_nsfw(Some(data.show_nsfw))
- .accepted_application(accepted_application)
- .default_listing_type(Some(local_site.default_post_listing_type))
- .build();
-
- let inserted_local_user = LocalUser::create(&mut context.pool(), &local_user_form).await?;
-
- if local_site.site_setup && require_registration_application {
- // Create the registration application
- let form = RegistrationApplicationInsertForm {
- local_user_id: inserted_local_user.id,
- // We already made sure answer was not null above
- answer: data.answer.clone().expect("must have an answer"),
- };
-
- RegistrationApplication::create(&mut context.pool(), &form).await?;
- }
-
- // Email the admins
- if local_site.application_email_admins {
- send_new_applicant_email_to_admins(&data.username, &mut context.pool(), context.settings())
- .await?;
+ let slur_regex = local_site_to_slur_regex(&local_site);
+ check_slurs(&data.username, &slur_regex)?;
+ check_slurs_opt(&data.answer, &slur_regex)?;
+ let username = sanitize_html(&data.username);
+
+ let actor_keypair = generate_actor_keypair()?;
+ is_valid_actor_name(&data.username, local_site.actor_name_max_length as usize)?;
+ let actor_id = generate_local_apub_endpoint(
+ EndpointType::Person,
+ &data.username,
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+
+ if let Some(email) = &data.email {
+ if LocalUser::is_email_taken(&mut context.pool(), email).await? {
+ return Err(LemmyErrorType::EmailAlreadyExists)?;
}
+ }
- let mut login_response = LoginResponse {
- jwt: None,
- registration_created: false,
- verify_email_sent: false,
+ // We have to create both a person, and local_user
+
+ // Register the new person
+ let person_form = PersonInsertForm::builder()
+ .name(username)
+ .actor_id(Some(actor_id.clone()))
+ .private_key(Some(actor_keypair.private_key))
+ .public_key(actor_keypair.public_key)
+ .inbox_url(Some(generate_inbox_url(&actor_id)?))
+ .shared_inbox_url(Some(generate_shared_inbox_url(&actor_id)?))
+ // If its the initial site setup, they are an admin
+ .admin(Some(!local_site.site_setup))
+ .instance_id(site_view.site.instance_id)
+ .build();
+
+ // insert the person
+ let inserted_person = Person::create(&mut context.pool(), &person_form)
+ .await
+ .with_lemmy_type(LemmyErrorType::UserAlreadyExists)?;
+
+ // Automatically set their application as accepted, if they created this with open registration.
+ // Also fixes a bug which allows users to log in when registrations are changed to closed.
+ let accepted_application = Some(!require_registration_application);
+
+ // Create the local user
+ let local_user_form = LocalUserInsertForm::builder()
+ .person_id(inserted_person.id)
+ .email(data.email.as_deref().map(str::to_lowercase))
+ .password_encrypted(data.password.to_string())
+ .show_nsfw(Some(data.show_nsfw))
+ .accepted_application(accepted_application)
+ .default_listing_type(Some(local_site.default_post_listing_type))
+ .build();
+
+ let inserted_local_user = LocalUser::create(&mut context.pool(), &local_user_form).await?;
+
+ if local_site.site_setup && require_registration_application {
+ // Create the registration application
+ let form = RegistrationApplicationInsertForm {
+ local_user_id: inserted_local_user.id,
+ // We already made sure answer was not null above
+ answer: data.answer.clone().expect("must have an answer"),
};
- // Log the user in directly if the site is not setup, or email verification and application aren't required
- if !local_site.site_setup
- || (!require_registration_application && !local_site.require_email_verification)
- {
- login_response.jwt = Some(
- Claims::jwt(
- inserted_local_user.id.0,
- &context.secret().jwt_secret,
- &context.settings().hostname,
- )?
- .into(),
- );
- } else {
- if local_site.require_email_verification {
- let local_user_view = LocalUserView {
- local_user: inserted_local_user,
- person: inserted_person,
- counts: PersonAggregates::default(),
- };
- // we check at the beginning of this method that email is set
- let email = local_user_view
- .local_user
- .email
- .clone()
- .expect("email was provided");
-
- send_verification_email(
- &local_user_view,
- &email,
- &mut context.pool(),
- context.settings(),
- )
- .await?;
- login_response.verify_email_sent = true;
- }
+ RegistrationApplication::create(&mut context.pool(), &form).await?;
+ }
- if require_registration_application {
- login_response.registration_created = true;
- }
+ // Email the admins
+ if local_site.application_email_admins {
+ send_new_applicant_email_to_admins(&data.username, &mut context.pool(), context.settings())
+ .await?;
+ }
+
+ let mut login_response = LoginResponse {
+ jwt: None,
+ registration_created: false,
+ verify_email_sent: false,
+ };
+
+ // Log the user in directly if the site is not setup, or email verification and application aren't required
+ if !local_site.site_setup
+ || (!require_registration_application && !local_site.require_email_verification)
+ {
+ login_response.jwt = Some(
+ Claims::jwt(
+ inserted_local_user.id.0,
+ &context.secret().jwt_secret,
+ &context.settings().hostname,
+ )?
+ .into(),
+ );
+ } else {
+ if local_site.require_email_verification {
+ let local_user_view = LocalUserView {
+ local_user: inserted_local_user,
+ person: inserted_person,
+ counts: PersonAggregates::default(),
+ };
+ // we check at the beginning of this method that email is set
+ let email = local_user_view
+ .local_user
+ .email
+ .clone()
+ .expect("email was provided");
+
+ send_verification_email(
+ &local_user_view,
+ &email,
+ &mut context.pool(),
+ context.settings(),
+ )
+ .await?;
+ login_response.verify_email_sent = true;
}
- Ok(login_response)
+ if require_registration_application {
+ login_response.registration_created = true;
+ }
}
+
+ Ok(Json(login_response))
}
-use crate::PerformCrud;
-use actix_web::web::Data;
+use activitypub_federation::config::Data;
+use actix_web::web::Json;
use bcrypt::verify;
use lemmy_api_common::{
context::LemmyContext,
person::{DeleteAccount, DeleteAccountResponse},
+ send_activity::{ActivityChannel, SendActivityData},
utils::local_user_view_from_jwt,
};
use lemmy_utils::error::{LemmyError, LemmyErrorType};
-#[async_trait::async_trait(?Send)]
-impl PerformCrud for DeleteAccount {
- type Response = DeleteAccountResponse;
+#[tracing::instrument(skip(context))]
+pub async fn delete_account(
+ data: Json<DeleteAccount>,
+ context: Data<LemmyContext>,
+) -> Result<Json<DeleteAccountResponse>, LemmyError> {
+ let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), &context).await?;
- #[tracing::instrument(skip(self, context))]
- async fn perform(&self, context: &Data<LemmyContext>) -> Result<Self::Response, LemmyError> {
- let data = self;
- let local_user_view = local_user_view_from_jwt(data.auth.as_ref(), context).await?;
+ // Verify the password
+ let valid: bool = verify(
+ &data.password,
+ &local_user_view.local_user.password_encrypted,
+ )
+ .unwrap_or(false);
+ if !valid {
+ return Err(LemmyErrorType::IncorrectLogin)?;
+ }
- // Verify the password
- let valid: bool = verify(
- &data.password,
- &local_user_view.local_user.password_encrypted,
- )
- .unwrap_or(false);
- if !valid {
- return Err(LemmyErrorType::IncorrectLogin)?;
- }
+ ActivityChannel::submit_activity(
+ SendActivityData::DeleteUser(local_user_view.person),
+ &context,
+ )
+ .await?;
- Ok(DeleteAccountResponse {})
- }
+ Ok(Json(DeleteAccountResponse {}))
}
-mod create;
-mod delete;
+pub mod create;
+pub mod delete;
use crate::{
- objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson},
+ objects::{community::ApubCommunity, instance::ApubSite},
protocol::{
activities::block::{block_user::BlockUser, undo_block_user::UndoBlockUser},
objects::{group::Group, instance::Instance},
},
- SendActivity,
};
use activitypub_federation::{
config::Data,
traits::{Actor, Object},
};
use chrono::NaiveDateTime;
-use lemmy_api_common::{
- community::{BanFromCommunity, BanFromCommunityResponse},
- context::LemmyContext,
- person::{BanPerson, BanPersonResponse},
- utils::local_user_view_from_jwt,
-};
+use lemmy_api_common::{community::BanFromCommunity, context::LemmyContext, person::BanPerson};
use lemmy_db_schema::{
+ newtypes::CommunityId,
source::{community::Community, person::Person, site::Site},
traits::Crud,
utils::DbPool,
};
use lemmy_db_views::structs::SiteView;
-use lemmy_utils::{error::LemmyError, utils::time::naive_from_unix};
+use lemmy_utils::{
+ error::{LemmyError, LemmyResult},
+ utils::time::naive_from_unix,
+};
use serde::Deserialize;
use url::Url;
})
}
-#[async_trait::async_trait]
-impl SendActivity for BanPerson {
- type Response = BanPersonResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let person = Person::read(&mut context.pool(), request.person_id).await?;
- let site = SiteOrCommunity::Site(SiteView::read_local(&mut 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]
-impl SendActivity for BanFromCommunity {
- type Response = BanFromCommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community: ApubCommunity = Community::read(&mut context.pool(), request.community_id)
- .await?
- .into();
- let banned_person: ApubPerson = Person::read(&mut context.pool(), request.person_id)
- .await?
- .into();
- let expires = request.expires.map(naive_from_unix);
-
- if request.ban {
+pub(crate) async fn send_ban_from_site(
+ mod_: Person,
+ banned_user: Person,
+ data: BanPerson,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let site = SiteOrCommunity::Site(SiteView::read_local(&mut context.pool()).await?.site.into());
+ let expires = data.expires.map(naive_from_unix);
+
+ // if the action affects a local user, federate to other instances
+ if banned_user.local {
+ if data.ban {
BlockUser::send(
- &SiteOrCommunity::Community(community),
- &banned_person,
- &local_user_view.person.clone().into(),
- request.remove_data.unwrap_or(false),
- request.reason.clone(),
+ &site,
+ &banned_user.into(),
+ &mod_.into(),
+ data.remove_data.unwrap_or(false),
+ data.reason.clone(),
expires,
- context,
+ &context,
)
.await
} else {
UndoBlockUser::send(
- &SiteOrCommunity::Community(community),
- &banned_person,
- &local_user_view.person.clone().into(),
- request.reason.clone(),
- context,
+ &site,
+ &banned_user.into(),
+ &mod_.into(),
+ data.reason.clone(),
+ &context,
)
.await
}
+ } else {
+ Ok(())
+ }
+}
+
+pub(crate) async fn send_ban_from_community(
+ mod_: Person,
+ community_id: CommunityId,
+ banned_person: Person,
+ data: BanFromCommunity,
+ context: Data<LemmyContext>,
+) -> LemmyResult<()> {
+ let community: ApubCommunity = Community::read(&mut context.pool(), community_id)
+ .await?
+ .into();
+ let expires = data.expires.map(naive_from_unix);
+
+ if data.ban {
+ BlockUser::send(
+ &SiteOrCommunity::Community(community),
+ &banned_person.into(),
+ &mod_.into(),
+ data.remove_data.unwrap_or(false),
+ data.reason.clone(),
+ expires,
+ &context,
+ )
+ .await
+ } else {
+ UndoBlockUser::send(
+ &SiteOrCommunity::Community(community),
+ &banned_person.into(),
+ &mod_.into(),
+ data.reason.clone(),
+ &context,
+ )
+ .await
}
}
activities::community::{collection_add::CollectionAdd, collection_remove::CollectionRemove},
InCommunity,
},
- SendActivity,
};
use activitypub_federation::{
config::Data,
traits::{ActivityHandler, Actor},
};
use lemmy_api_common::{
- community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
- post::{FeaturePost, PostResponse},
- utils::{generate_featured_url, generate_moderators_url, local_user_view_from_jwt},
+ utils::{generate_featured_url, generate_moderators_url},
};
use lemmy_db_schema::{
impls::community::CollectionType,
+ newtypes::{CommunityId, PersonId},
source::{
community::{Community, CommunityModerator, CommunityModeratorForm},
moderator::{ModAddCommunity, ModAddCommunityForm},
}
}
-#[async_trait::async_trait]
-impl SendActivity for AddModToCommunity {
- type Response = AddModToCommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community: ApubCommunity = Community::read(&mut context.pool(), request.community_id)
- .await?
- .into();
- let updated_mod: ApubPerson = Person::read(&mut context.pool(), request.person_id)
- .await?
- .into();
- if request.added {
- CollectionAdd::send_add_mod(
- &community,
- &updated_mod,
- &local_user_view.person.into(),
- context,
- )
- .await
- } else {
- CollectionRemove::send_remove_mod(
- &community,
- &updated_mod,
- &local_user_view.person.into(),
- context,
- )
- .await
- }
+pub(crate) async fn send_add_mod_to_community(
+ actor: Person,
+ community_id: CommunityId,
+ updated_mod_id: PersonId,
+ added: bool,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let actor: ApubPerson = actor.into();
+ let community: ApubCommunity = Community::read(&mut context.pool(), community_id)
+ .await?
+ .into();
+ let updated_mod: ApubPerson = Person::read(&mut context.pool(), updated_mod_id)
+ .await?
+ .into();
+ if added {
+ CollectionAdd::send_add_mod(&community, &updated_mod, &actor, &context).await
+ } else {
+ CollectionRemove::send_remove_mod(&community, &updated_mod, &actor, &context).await
}
}
-#[async_trait::async_trait]
-impl SendActivity for FeaturePost {
- type Response = PostResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), response.post_view.community.id)
- .await?
- .into();
- let post = response.post_view.post.clone().into();
- let person = local_user_view.person.into();
- if request.featured {
- CollectionAdd::send_add_featured_post(&community, &post, &person, context).await
- } else {
- CollectionRemove::send_remove_featured_post(&community, &post, &person, context).await
- }
+pub(crate) async fn send_feature_post(
+ post: Post,
+ actor: Person,
+ featured: bool,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let actor: ApubPerson = actor.into();
+ let post: ApubPost = post.into();
+ let community = Community::read(&mut context.pool(), post.community_id)
+ .await?
+ .into();
+ if featured {
+ CollectionAdd::send_add_featured_post(&community, &post, &actor, &context).await
+ } else {
+ CollectionRemove::send_remove_featured_post(&community, &post, &actor, &context).await
}
}
},
activity_lists::AnnouncableActivities,
insert_received_activity,
+ objects::community::ApubCommunity,
protocol::{
activities::community::lock_page::{LockPage, LockType, UndoLockPage},
InCommunity,
},
- SendActivity,
};
use activitypub_federation::{
config::Data,
+ fetch::object_id::ObjectId,
kinds::{activity::UndoType, public},
traits::ActivityHandler,
};
-use lemmy_api_common::{
- context::LemmyContext,
- post::{LockPost, PostResponse},
- utils::local_user_view_from_jwt,
-};
+use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
community::Community,
+ person::Person,
post::{Post, PostUpdateForm},
},
traits::Crud,
}
}
-#[async_trait::async_trait]
-impl SendActivity for LockPost {
- type Response = PostResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
+pub(crate) async fn send_lock_post(
+ post: Post,
+ actor: Person,
+ locked: bool,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let community: ApubCommunity = Community::read(&mut context.pool(), post.community_id)
+ .await?
+ .into();
+ let id = generate_activity_id(
+ LockType::Lock,
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+ let community_id = community.actor_id.inner().clone();
+ let lock = LockPage {
+ actor: actor.actor_id.clone().into(),
+ to: vec![public()],
+ object: ObjectId::from(post.ap_id),
+ cc: vec![community_id.clone()],
+ kind: LockType::Lock,
+ id,
+ audience: Some(community_id.into()),
+ };
+ let activity = if locked {
+ AnnouncableActivities::LockPost(lock)
+ } else {
let id = generate_activity_id(
- LockType::Lock,
+ UndoType::Undo,
&context.settings().get_protocol_and_hostname(),
)?;
- let community_id = response.post_view.community.actor_id.clone();
- let actor = local_user_view.person.actor_id.clone().into();
- let lock = LockPage {
- actor,
+ let undo = UndoLockPage {
+ actor: lock.actor.clone(),
to: vec![public()],
- object: response.post_view.post.ap_id.clone().into(),
- cc: vec![community_id.clone().into()],
- kind: LockType::Lock,
+ cc: lock.cc.clone(),
+ kind: UndoType::Undo,
id,
- audience: Some(community_id.into()),
+ audience: lock.audience.clone(),
+ object: lock,
};
- let activity = if request.locked {
- AnnouncableActivities::LockPost(lock)
- } else {
- let id = generate_activity_id(
- UndoType::Undo,
- &context.settings().get_protocol_and_hostname(),
- )?;
- let undo = UndoLockPage {
- actor: lock.actor.clone(),
- to: vec![public()],
- cc: lock.cc.clone(),
- kind: UndoType::Undo,
- id,
- audience: lock.audience.clone(),
- object: lock,
- };
- AnnouncableActivities::UndoLockPost(undo)
- };
- let community = Community::read(&mut context.pool(), response.post_view.community.id).await?;
- send_activity_in_community(
- activity,
- &local_user_view.person.into(),
- &community.into(),
- vec![],
- true,
- context,
- )
- .await?;
- Ok(())
- }
+ AnnouncableActivities::UndoLockPost(undo)
+ };
+ send_activity_in_community(activity, &actor.into(), &community, vec![], true, &context).await?;
+ Ok(())
}
objects::{community::ApubCommunity, person::ApubPerson},
protocol::{activities::community::report::Report, InCommunity},
PostOrComment,
- SendActivity,
};
use activitypub_federation::{
config::Data,
kinds::activity::FlagType,
traits::{ActivityHandler, Actor},
};
-use lemmy_api_common::{
- comment::{CommentReportResponse, CreateCommentReport},
- context::LemmyContext,
- post::{CreatePostReport, PostReportResponse},
- utils::{local_user_view_from_jwt, sanitize_html},
-};
+use lemmy_api_common::{context::LemmyContext, utils::sanitize_html};
use lemmy_db_schema::{
source::{
comment_report::{CommentReport, CommentReportForm},
+ community::Community,
+ person::Person,
post_report::{PostReport, PostReportForm},
},
traits::Reportable,
use lemmy_utils::error::LemmyError;
use url::Url;
-#[async_trait::async_trait]
-impl SendActivity for CreatePostReport {
- type Response = PostReportResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- Report::send(
- ObjectId::from(response.post_report_view.post.ap_id.clone()),
- &local_user_view.person.into(),
- ObjectId::from(response.post_report_view.community.actor_id.clone()),
- request.reason.to_string(),
- context,
- )
- .await
- }
-}
-
-#[async_trait::async_trait]
-impl SendActivity for CreateCommentReport {
- type Response = CommentReportResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- Report::send(
- ObjectId::from(response.comment_report_view.comment.ap_id.clone()),
- &local_user_view.person.into(),
- ObjectId::from(response.comment_report_view.community.actor_id.clone()),
- request.reason.to_string(),
- context,
- )
- .await
- }
-}
-
impl Report {
#[tracing::instrument(skip_all)]
- async fn send(
+ pub(crate) async fn send(
object_id: ObjectId<PostOrComment>,
- actor: &ApubPerson,
- community_id: ObjectId<ApubCommunity>,
+ actor: Person,
+ community: Community,
reason: String,
- context: &Data<LemmyContext>,
+ context: Data<LemmyContext>,
) -> Result<(), LemmyError> {
- let community = community_id.dereference_local(context).await?;
+ let actor: ApubPerson = actor.into();
+ let community: ApubCommunity = community.into();
let kind = FlagType::Flag;
let id = generate_activity_id(
kind.clone(),
};
let inbox = vec![community.shared_inbox_or_inbox()];
- send_lemmy_activity(context, report, actor, inbox, false).await
+ send_lemmy_activity(&context, report, &actor, inbox, false).await
}
}
insert_received_activity,
objects::{community::ApubCommunity, person::ApubPerson},
protocol::{activities::community::update::UpdateCommunity, InCommunity},
- SendActivity,
};
use activitypub_federation::{
config::Data,
kinds::{activity::UpdateType, public},
traits::{ActivityHandler, Actor, Object},
};
-use lemmy_api_common::{
- community::{CommunityResponse, EditCommunity, HideCommunity},
- context::LemmyContext,
- utils::local_user_view_from_jwt,
+use lemmy_api_common::context::LemmyContext;
+use lemmy_db_schema::{
+ source::{community::Community, person::Person},
+ traits::Crud,
};
-use lemmy_db_schema::{source::community::Community, traits::Crud};
use lemmy_utils::error::LemmyError;
use url::Url;
-#[async_trait::async_trait]
-impl SendActivity for EditCommunity {
- type Response = CommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), request.community_id).await?;
- UpdateCommunity::send(community.into(), &local_user_view.person.into(), context).await
- }
-}
-
-impl UpdateCommunity {
- #[tracing::instrument(skip_all)]
- pub async fn send(
- community: ApubCommunity,
- actor: &ApubPerson,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let id = generate_activity_id(
- UpdateType::Update,
- &context.settings().get_protocol_and_hostname(),
- )?;
- let update = UpdateCommunity {
- actor: actor.id().into(),
- to: vec![public()],
- object: Box::new(community.clone().into_json(context).await?),
- cc: vec![community.id()],
- kind: UpdateType::Update,
- id: id.clone(),
- audience: Some(community.id().into()),
- };
+pub(crate) async fn send_update_community(
+ community: Community,
+ actor: Person,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let community: ApubCommunity = community.into();
+ let actor: ApubPerson = actor.into();
+ let id = generate_activity_id(
+ UpdateType::Update,
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+ let update = UpdateCommunity {
+ actor: actor.id().into(),
+ to: vec![public()],
+ object: Box::new(community.clone().into_json(&context).await?),
+ cc: vec![community.id()],
+ kind: UpdateType::Update,
+ id: id.clone(),
+ audience: Some(community.id().into()),
+ };
- let activity = AnnouncableActivities::UpdateCommunity(update);
- send_activity_in_community(activity, actor, &community, vec![], true, context).await
- }
+ let activity = AnnouncableActivities::UpdateCommunity(update);
+ send_activity_in_community(activity, &actor, &community, vec![], true, &context).await
}
#[async_trait::async_trait]
Ok(())
}
}
-
-#[async_trait::async_trait]
-impl SendActivity for HideCommunity {
- type Response = CommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), request.community_id).await?;
- UpdateCommunity::send(community.into(), &local_user_view.person.into(), context).await
- }
-}
create_or_update::chat_message::CreateOrUpdateChatMessage,
CreateOrUpdateType,
},
- SendActivity,
};
use activitypub_federation::{
config::Data,
protocol::verification::verify_domains_match,
traits::{ActivityHandler, Actor, Object},
};
-use lemmy_api_common::{
- context::LemmyContext,
- private_message::{CreatePrivateMessage, EditPrivateMessage, PrivateMessageResponse},
-};
-use lemmy_db_schema::{
- newtypes::PersonId,
- source::{person::Person, private_message::PrivateMessage},
- traits::Crud,
-};
+use lemmy_api_common::context::LemmyContext;
+use lemmy_db_views::structs::PrivateMessageView;
use lemmy_utils::error::LemmyError;
use url::Url;
-#[async_trait::async_trait]
-impl SendActivity for CreatePrivateMessage {
- type Response = PrivateMessageResponse;
-
- async fn send_activity(
- _request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- CreateOrUpdateChatMessage::send(
- &response.private_message_view.private_message,
- response.private_message_view.creator.id,
- CreateOrUpdateType::Create,
- context,
- )
- .await
- }
-}
-#[async_trait::async_trait]
-impl SendActivity for EditPrivateMessage {
- type Response = PrivateMessageResponse;
+pub(crate) async fn send_create_or_update_pm(
+ pm_view: PrivateMessageView,
+ kind: CreateOrUpdateType,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let actor: ApubPerson = pm_view.creator.into();
+ let recipient: ApubPerson = pm_view.recipient.into();
- async fn send_activity(
- _request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- CreateOrUpdateChatMessage::send(
- &response.private_message_view.private_message,
- response.private_message_view.creator.id,
- CreateOrUpdateType::Update,
- context,
- )
- .await
- }
-}
-
-impl CreateOrUpdateChatMessage {
- #[tracing::instrument(skip_all)]
- async fn send(
- private_message: &PrivateMessage,
- sender_id: PersonId,
- kind: CreateOrUpdateType,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let recipient_id = private_message.recipient_id;
- let sender: ApubPerson = Person::read(&mut context.pool(), sender_id).await?.into();
- let recipient: ApubPerson = Person::read(&mut context.pool(), recipient_id)
- .await?
- .into();
-
- let id = generate_activity_id(
- kind.clone(),
- &context.settings().get_protocol_and_hostname(),
- )?;
- let create_or_update = CreateOrUpdateChatMessage {
- id: id.clone(),
- actor: sender.id().into(),
- to: [recipient.id().into()],
- object: ApubPrivateMessage(private_message.clone())
- .into_json(context)
- .await?,
- kind,
- };
- let inbox = vec![recipient.shared_inbox_or_inbox()];
- send_lemmy_activity(context, create_or_update, &sender, inbox, true).await
- }
+ let id = generate_activity_id(
+ kind.clone(),
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+ let create_or_update = CreateOrUpdateChatMessage {
+ id: id.clone(),
+ actor: actor.id().into(),
+ to: [recipient.id().into()],
+ object: ApubPrivateMessage(pm_view.private_message.clone())
+ .into_json(&context)
+ .await?,
+ kind,
+ };
+ let inbox = vec![recipient.shared_inbox_or_inbox()];
+ send_lemmy_activity(&context, create_or_update, &actor, inbox, true).await
}
#[async_trait::async_trait]
insert_received_activity,
objects::{instance::remote_instance_inboxes, person::ApubPerson},
protocol::activities::deletion::delete_user::DeleteUser,
- SendActivity,
};
use activitypub_federation::{
config::Data,
protocol::verification::verify_urls_match,
traits::{ActivityHandler, Actor},
};
-use lemmy_api_common::{
- context::LemmyContext,
- person::{DeleteAccount, DeleteAccountResponse},
- utils::{delete_user_account, local_user_view_from_jwt},
-};
+use lemmy_api_common::{context::LemmyContext, utils::delete_user_account};
+use lemmy_db_schema::source::person::Person;
use lemmy_utils::error::LemmyError;
use url::Url;
-#[async_trait::async_trait]
-impl SendActivity for DeleteAccount {
- type Response = DeleteAccountResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let actor: ApubPerson = local_user_view.person.into();
- delete_user_account(
- actor.id,
- &mut context.pool(),
- context.settings(),
- context.client(),
- )
- .await?;
+pub async fn delete_user(person: Person, context: Data<LemmyContext>) -> Result<(), LemmyError> {
+ let actor: ApubPerson = person.into();
+ delete_user_account(
+ actor.id,
+ &mut context.pool(),
+ context.settings(),
+ context.client(),
+ )
+ .await?;
- let id = generate_activity_id(
- DeleteType::Delete,
- &context.settings().get_protocol_and_hostname(),
- )?;
- let delete = DeleteUser {
- actor: actor.id().into(),
- to: vec![public()],
- object: actor.id().into(),
- kind: DeleteType::Delete,
- id: id.clone(),
- cc: vec![],
- };
+ let id = generate_activity_id(
+ DeleteType::Delete,
+ &context.settings().get_protocol_and_hostname(),
+ )?;
+ let delete = DeleteUser {
+ actor: actor.id().into(),
+ to: vec![public()],
+ object: actor.id().into(),
+ kind: DeleteType::Delete,
+ id: id.clone(),
+ cc: vec![],
+ };
- let inboxes = remote_instance_inboxes(&mut context.pool()).await?;
- send_lemmy_activity(context, delete, &actor, inboxes, true).await?;
- Ok(())
- }
+ let inboxes = remote_instance_inboxes(&mut context.pool()).await?;
+ send_lemmy_activity(&context, delete, &actor, inboxes, true).await?;
+ Ok(())
}
/// This can be separate from Delete activity because it doesn't need to be handled in shared inbox
activities::deletion::{delete::Delete, undo_delete::UndoDelete},
InCommunity,
},
- SendActivity,
};
use activitypub_federation::{
config::Data,
protocol::verification::verify_domains_match,
traits::{Actor, Object},
};
-use lemmy_api_common::{
- community::{CommunityResponse, DeleteCommunity, RemoveCommunity},
- context::LemmyContext,
- post::{DeletePost, PostResponse, RemovePost},
- private_message::{DeletePrivateMessage, PrivateMessageResponse},
- utils::local_user_view_from_jwt,
-};
+use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
+ newtypes::CommunityId,
source::{
comment::{Comment, CommentUpdateForm},
community::{Community, CommunityUpdateForm},
pub mod delete_user;
pub mod undo_delete;
-#[async_trait::async_trait]
-impl SendActivity for DeletePost {
- type Response = PostResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), response.post_view.community.id).await?;
- let deletable = DeletableObjects::Post(response.post_view.post.clone().into());
- send_apub_delete_in_community(
- local_user_view.person,
- community,
- deletable,
- None,
- request.deleted,
- context,
- )
- .await
- }
-}
-
-#[async_trait::async_trait]
-impl SendActivity for RemovePost {
- type Response = PostResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), response.post_view.community.id).await?;
- let deletable = DeletableObjects::Post(response.post_view.post.clone().into());
- send_apub_delete_in_community(
- local_user_view.person,
- community,
- deletable,
- request.reason.clone().or_else(|| Some(String::new())),
- request.removed,
- context,
- )
- .await
- }
-}
-
-#[async_trait::async_trait]
-impl SendActivity for DeletePrivateMessage {
- type Response = PrivateMessageResponse;
-
- async fn send_activity(
- request: &Self,
- response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- send_apub_delete_private_message(
- &local_user_view.person.into(),
- response.private_message_view.private_message.clone(),
- request.deleted,
- context,
- )
- .await
- }
-}
-
-#[async_trait::async_trait]
-impl SendActivity for DeleteCommunity {
- type Response = CommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), request.community_id).await?;
- let deletable = DeletableObjects::Community(community.clone().into());
- send_apub_delete_in_community(
- local_user_view.person,
- community,
- deletable,
- None,
- request.deleted,
- context,
- )
- .await
- }
-}
-
-#[async_trait::async_trait]
-impl SendActivity for RemoveCommunity {
- type Response = CommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), request.community_id).await?;
- let deletable = DeletableObjects::Community(community.clone().into());
- send_apub_delete_in_community(
- local_user_view.person,
- community,
- deletable,
- request.reason.clone().or_else(|| Some(String::new())),
- request.removed,
- context,
- )
- .await
- }
-}
-
/// Parameter `reason` being set indicates that this is a removal by a mod. If its unset, this
/// action was done by a normal user.
#[tracing::instrument(skip_all)]
.await
}
+/// Parameter `reason` being set indicates that this is a removal by a mod. If its unset, this
+/// action was done by a normal user.
+#[tracing::instrument(skip_all)]
+pub(crate) async fn send_apub_delete_in_community_new(
+ actor: Person,
+ community_id: CommunityId,
+ object: DeletableObjects,
+ reason: Option<String>,
+ deleted: bool,
+ context: Data<LemmyContext>,
+) -> Result<(), LemmyError> {
+ let community = Community::read(&mut context.pool(), community_id).await?;
+ let actor = ApubPerson::from(actor);
+ let is_mod_action = reason.is_some();
+ let activity = if deleted {
+ let delete = Delete::new(&actor, object, public(), Some(&community), reason, &context)?;
+ AnnouncableActivities::Delete(delete)
+ } else {
+ let undo = UndoDelete::new(&actor, object, public(), Some(&community), reason, &context)?;
+ AnnouncableActivities::UndoDelete(undo)
+ };
+ send_activity_in_community(
+ activity,
+ &actor,
+ &community.into(),
+ vec![],
+ is_mod_action,
+ &context,
+ )
+ .await
+}
+
#[tracing::instrument(skip_all)]
-async fn send_apub_delete_private_message(
+pub(crate) async fn send_apub_delete_private_message(
actor: &ApubPerson,
pm: PrivateMessage,
deleted: bool,
- context: &Data<LemmyContext>,
+ context: Data<LemmyContext>,
) -> Result<(), LemmyError> {
let recipient_id = pm.recipient_id;
let recipient: ApubPerson = Person::read(&mut context.pool(), recipient_id)
let deletable = DeletableObjects::PrivateMessage(pm.into());
let inbox = vec![recipient.shared_inbox_or_inbox()];
if deleted {
- let delete = Delete::new(actor, deletable, recipient.id(), None, None, context)?;
- send_lemmy_activity(context, delete, actor, inbox, true).await?;
+ let delete = Delete::new(actor, deletable, recipient.id(), None, None, &context)?;
+ send_lemmy_activity(&context, delete, actor, inbox, true).await?;
} else {
- let undo = UndoDelete::new(actor, deletable, recipient.id(), None, None, context)?;
- send_lemmy_activity(context, undo, actor, inbox, true).await?;
+ let undo = UndoDelete::new(actor, deletable, recipient.id(), None, None, &context)?;
+ send_lemmy_activity(&context, undo, actor, inbox, true).await?;
};
Ok(())
}
fetcher::user_or_community::UserOrCommunity,
insert_received_activity,
objects::{community::ApubCommunity, person::ApubPerson},
- protocol::activities::following::{
- accept::AcceptFollow,
- follow::Follow,
- undo_follow::UndoFollow,
- },
- SendActivity,
+ protocol::activities::following::{accept::AcceptFollow, follow::Follow},
};
use activitypub_federation::{
config::Data,
protocol::verification::verify_urls_match,
traits::{ActivityHandler, Actor},
};
-use lemmy_api_common::{
- community::{BlockCommunity, BlockCommunityResponse},
- context::LemmyContext,
- utils::local_user_view_from_jwt,
-};
+use lemmy_api_common::context::LemmyContext;
use lemmy_db_schema::{
source::{
- community::{Community, CommunityFollower, CommunityFollowerForm},
+ community::{CommunityFollower, CommunityFollowerForm},
person::{PersonFollower, PersonFollowerForm},
},
- traits::{Crud, Followable},
+ traits::Followable,
};
use lemmy_utils::error::LemmyError;
use url::Url;
AcceptFollow::send(self, context).await
}
}
-
-#[async_trait::async_trait]
-impl SendActivity for BlockCommunity {
- type Response = BlockCommunityResponse;
-
- async fn send_activity(
- request: &Self,
- _response: &Self::Response,
- context: &Data<LemmyContext>,
- ) -> Result<(), LemmyError> {
- let local_user_view = local_user_view_from_jwt(&request.auth, context).await?;
- let community = Community::read(&mut context.pool(), request.community_id).await?;
- UndoFollow::send(&local_user_view.person.into(), &community.into(), context).await
- }
-}
use self::following::send_follow_community;
use crate::{
activities::{
- deletion::{send_apub_delete_in_community, DeletableObjects},
+ block::{send_ban_from_community, send_ban_from_site},
+ community::{
+ collection_add::{send_add_mod_to_community, send_feature_post},
+ lock_page::send_lock_post,
+ update::send_update_community,
+ },
+ create_or_update::private_message::send_create_or_update_pm,
+ deletion::{
+ delete_user::delete_user,
+ send_apub_delete_in_community,
+ send_apub_delete_in_community_new,
+ send_apub_delete_private_message,
+ DeletableObjects,
+ },
voting::send_like_activity,
},
objects::{community::ApubCommunity, person::ApubPerson},
protocol::activities::{
+ community::report::Report,
create_or_update::{note::CreateOrUpdateNote, page::CreateOrUpdatePage},
CreateOrUpdateType,
},
let fed_task = async {
use SendActivityData::*;
match data {
- CreatePost(post) | UpdatePost(post) => {
+ CreatePost(post) => {
let creator_id = post.creator_id;
CreateOrUpdatePage::send(post, creator_id, CreateOrUpdateType::Create, context).await
}
- CreateComment(comment) | UpdateComment(comment) => {
+ UpdatePost(post) => {
+ let creator_id = post.creator_id;
+ CreateOrUpdatePage::send(post, creator_id, CreateOrUpdateType::Update, context).await
+ }
+ DeletePost(post, person, data) => {
+ send_apub_delete_in_community_new(
+ person,
+ post.community_id,
+ DeletableObjects::Post(post.into()),
+ None,
+ data.deleted,
+ context,
+ )
+ .await
+ }
+ RemovePost(post, person, data) => {
+ send_apub_delete_in_community_new(
+ person,
+ post.community_id,
+ DeletableObjects::Post(post.into()),
+ data.reason.or_else(|| Some(String::new())),
+ data.removed,
+ context,
+ )
+ .await
+ }
+ LockPost(post, actor, locked) => send_lock_post(post, actor, locked, context).await,
+ FeaturePost(post, actor, featured) => send_feature_post(post, actor, featured, context).await,
+ CreateComment(comment) => {
let creator_id = comment.creator_id;
CreateOrUpdateNote::send(comment, creator_id, CreateOrUpdateType::Create, context).await
}
+ UpdateComment(comment) => {
+ let creator_id = comment.creator_id;
+ CreateOrUpdateNote::send(comment, creator_id, CreateOrUpdateType::Update, context).await
+ }
DeleteComment(comment, actor, community) => {
let is_deleted = comment.deleted;
let deletable = DeletableObjects::Comment(comment.into());
LikePostOrComment(object_id, person, community, score) => {
send_like_activity(object_id, person, community, score, context).await
}
- SendActivityData::FollowCommunity(community, person, follow) => {
+ FollowCommunity(community, person, follow) => {
send_follow_community(community, person, follow, &context).await
}
+ UpdateCommunity(actor, community) => send_update_community(community, actor, context).await,
+ DeleteCommunity(actor, community, removed) => {
+ let deletable = DeletableObjects::Community(community.clone().into());
+ send_apub_delete_in_community(actor, community, deletable, None, removed, &context).await
+ }
+ RemoveCommunity(actor, community, reason, removed) => {
+ let deletable = DeletableObjects::Community(community.clone().into());
+ send_apub_delete_in_community(
+ actor,
+ community,
+ deletable,
+ reason.clone().or_else(|| Some(String::new())),
+ removed,
+ &context,
+ )
+ .await
+ }
+ AddModToCommunity(actor, community_id, updated_mod_id, added) => {
+ send_add_mod_to_community(actor, community_id, updated_mod_id, added, context).await
+ }
+ BanFromCommunity(mod_, community_id, target, data) => {
+ send_ban_from_community(mod_, community_id, target, data, context).await
+ }
+ BanFromSite(mod_, target, data) => send_ban_from_site(mod_, target, data, context).await,
+ CreatePrivateMessage(pm) => {
+ send_create_or_update_pm(pm, CreateOrUpdateType::Create, context).await
+ }
+ UpdatePrivateMessage(pm) => {
+ send_create_or_update_pm(pm, CreateOrUpdateType::Update, context).await
+ }
+ DeletePrivateMessage(person, pm, deleted) => {
+ send_apub_delete_private_message(&person.into(), pm, deleted, context).await
+ }
+ DeleteUser(person) => delete_user(person, context).await,
+ CreateReport(url, actor, community, reason) => {
+ Report::send(ObjectId::from(url), actor, community, reason, context).await
+ }
}
};
if *SYNCHRONOUS_FEDERATION {
use actix_web::{guard, web, Error, HttpResponse, Result};
use lemmy_api::{
comment::{distinguish::distinguish_comment, like::like_comment, save::save_comment},
- comment_report::{list::list_comment_reports, resolve::resolve_comment_report},
- community::follow::follow_community,
- local_user::notifications::mark_reply_read::mark_reply_as_read,
- post::like::like_post,
+ comment_report::{
+ create::create_comment_report,
+ list::list_comment_reports,
+ resolve::resolve_comment_report,
+ },
+ community::{
+ add_mod::add_mod_to_community,
+ ban::ban_from_community,
+ block::block_community,
+ follow::follow_community,
+ hide::hide_community,
+ },
+ local_user::{ban_person::ban_from_site, notifications::mark_reply_read::mark_reply_as_read},
+ post::{feature::feature_post, like::like_post, lock::lock_post},
+ post_report::create::create_post_report,
Perform,
};
use lemmy_api_common::{
- comment::CreateCommentReport,
- community::{
- AddModToCommunity,
- BanFromCommunity,
- BlockCommunity,
- CreateCommunity,
- DeleteCommunity,
- EditCommunity,
- HideCommunity,
- RemoveCommunity,
- TransferCommunity,
- },
+ community::TransferCommunity,
context::LemmyContext,
- custom_emoji::{CreateCustomEmoji, DeleteCustomEmoji, EditCustomEmoji},
person::{
AddAdmin,
- BanPerson,
BlockPerson,
ChangePassword,
- DeleteAccount,
GetBannedPersons,
GetCaptcha,
GetPersonMentions,
MarkPersonMentionAsRead,
PasswordChangeAfterReset,
PasswordReset,
- Register,
SaveUserSettings,
VerifyEmail,
},
- post::{
- CreatePostReport,
- DeletePost,
- FeaturePost,
- GetSiteMetadata,
- ListPostReports,
- LockPost,
- MarkPostAsRead,
- RemovePost,
- ResolvePostReport,
- SavePost,
- },
+ post::{GetSiteMetadata, ListPostReports, MarkPostAsRead, ResolvePostReport, SavePost},
private_message::{
- CreatePrivateMessage,
CreatePrivateMessageReport,
- DeletePrivateMessage,
- EditPrivateMessage,
ListPrivateMessageReports,
MarkPrivateMessageAsRead,
ResolvePrivateMessageReport,
remove::remove_comment,
update::update_comment,
},
- community::list::list_communities,
- post::{create::create_post, read::get_post, update::update_post},
- private_message::read::get_private_message,
+ community::{
+ create::create_community,
+ delete::delete_community,
+ list::list_communities,
+ remove::remove_community,
+ update::update_community,
+ },
+ custom_emoji::{
+ create::create_custom_emoji,
+ delete::delete_custom_emoji,
+ update::update_custom_emoji,
+ },
+ post::{
+ create::create_post,
+ delete::delete_post,
+ read::get_post,
+ remove::remove_post,
+ update::update_post,
+ },
+ private_message::{
+ create::create_private_message,
+ delete::delete_private_message,
+ read::get_private_message,
+ update::update_private_message,
+ },
site::{create::create_site, read::get_site, update::update_site},
- PerformCrud,
+ user::{create::register, delete::delete_account},
};
use lemmy_apub::{
api::{
web::resource("/community")
.guard(guard::Post())
.wrap(rate_limit.register())
- .route(web::post().to(route_post_crud::<CreateCommunity>)),
+ .route(web::post().to(create_community)),
)
.service(
web::scope("/community")
.wrap(rate_limit.message())
.route("", web::get().to(get_community))
- .route("", web::put().to(route_post_crud::<EditCommunity>))
- .route("/hide", web::put().to(route_post::<HideCommunity>))
+ .route("", web::put().to(update_community))
+ .route("/hide", web::put().to(hide_community))
.route("/list", web::get().to(list_communities))
.route("/follow", web::post().to(follow_community))
- .route("/block", web::post().to(route_post::<BlockCommunity>))
- .route(
- "/delete",
- web::post().to(route_post_crud::<DeleteCommunity>),
- )
+ .route("/block", web::post().to(block_community))
+ .route("/delete", web::post().to(delete_community))
// Mod Actions
- .route(
- "/remove",
- web::post().to(route_post_crud::<RemoveCommunity>),
- )
+ .route("/remove", web::post().to(remove_community))
.route("/transfer", web::post().to(route_post::<TransferCommunity>))
- .route("/ban_user", web::post().to(route_post::<BanFromCommunity>))
- .route("/mod", web::post().to(route_post::<AddModToCommunity>)),
+ .route("/ban_user", web::post().to(ban_from_community))
+ .route("/mod", web::post().to(add_mod_to_community)),
)
.service(
web::scope("/federated_instances")
.wrap(rate_limit.message())
.route("", web::get().to(get_post))
.route("", web::put().to(update_post))
- .route("/delete", web::post().to(route_post_crud::<DeletePost>))
- .route("/remove", web::post().to(route_post_crud::<RemovePost>))
+ .route("/delete", web::post().to(delete_post))
+ .route("/remove", web::post().to(remove_post))
.route(
"/mark_as_read",
web::post().to(route_post::<MarkPostAsRead>),
)
- .route("/lock", web::post().to(route_post::<LockPost>))
- .route("/feature", web::post().to(route_post::<FeaturePost>))
+ .route("/lock", web::post().to(lock_post))
+ .route("/feature", web::post().to(feature_post))
.route("/list", web::get().to(list_posts))
.route("/like", web::post().to(like_post))
.route("/save", web::put().to(route_post::<SavePost>))
- .route("/report", web::post().to(route_post::<CreatePostReport>))
+ .route("/report", web::post().to(create_post_report))
.route(
"/report/resolve",
web::put().to(route_post::<ResolvePostReport>),
.route("/like", web::post().to(like_comment))
.route("/save", web::put().to(save_comment))
.route("/list", web::get().to(list_comments))
- .route("/report", web::post().to(route_post::<CreateCommentReport>))
+ .route("/report", web::post().to(create_comment_report))
.route("/report/resolve", web::put().to(resolve_comment_report))
.route("/report/list", web::get().to(list_comment_reports)),
)
web::scope("/private_message")
.wrap(rate_limit.message())
.route("/list", web::get().to(get_private_message))
- .route("", web::post().to(route_post_crud::<CreatePrivateMessage>))
- .route("", web::put().to(route_post_crud::<EditPrivateMessage>))
- .route(
- "/delete",
- web::post().to(route_post_crud::<DeletePrivateMessage>),
- )
+ .route("", web::post().to(create_private_message))
+ .route("", web::put().to(update_private_message))
+ .route("/delete", web::post().to(delete_private_message))
.route(
"/mark_as_read",
web::post().to(route_post::<MarkPrivateMessageAsRead>),
web::resource("/user/register")
.guard(guard::Post())
.wrap(rate_limit.register())
- .route(web::post().to(route_post_crud::<Register>)),
+ .route(web::post().to(register)),
)
.service(
// Handle captcha separately
)
.route("/replies", web::get().to(route_get::<GetReplies>))
// Admin action. I don't like that it's in /user
- .route("/ban", web::post().to(route_post::<BanPerson>))
+ .route("/ban", web::post().to(ban_from_site))
.route("/banned", web::get().to(route_get::<GetBannedPersons>))
.route("/block", web::post().to(route_post::<BlockPerson>))
// Account actions. I don't like that they're in /user maybe /accounts
.route("/login", web::post().to(route_post::<Login>))
- .route(
- "/delete_account",
- web::post().to(route_post_crud::<DeleteAccount>),
- )
+ .route("/delete_account", web::post().to(delete_account))
.route(
"/password_reset",
web::post().to(route_post::<PasswordReset>),
.service(
web::scope("/custom_emoji")
.wrap(rate_limit.message())
- .route("", web::post().to(route_post_crud::<CreateCustomEmoji>))
- .route("", web::put().to(route_post_crud::<EditCustomEmoji>))
- .route(
- "/delete",
- web::post().to(route_post_crud::<DeleteCustomEmoji>),
- ),
+ .route("", web::post().to(create_custom_emoji))
+ .route("", web::put().to(update_custom_emoji))
+ .route("/delete", web::post().to(delete_custom_emoji)),
),
);
}
{
perform::<Data>(data.0, context, apub_data).await
}
-
-async fn perform_crud<'a, Data>(
- data: Data,
- context: web::Data<LemmyContext>,
- apub_data: activitypub_federation::config::Data<LemmyContext>,
-) -> Result<HttpResponse, Error>
-where
- Data: PerformCrud
- + SendActivity<Response = <Data as PerformCrud>::Response>
- + Clone
- + Deserialize<'a>
- + Send
- + 'static,
-{
- let res = data.perform(&context).await?;
- let res_clone = res.clone();
- let fed_task = async move { SendActivity::send_activity(&data, &res_clone, &apub_data).await };
- if *SYNCHRONOUS_FEDERATION {
- fed_task.await?;
- } else {
- spawn_try_task(fed_task);
- }
- Ok(HttpResponse::Ok().json(&res))
-}
-
-async fn route_post_crud<'a, Data>(
- data: web::Json<Data>,
- context: web::Data<LemmyContext>,
- apub_data: activitypub_federation::config::Data<LemmyContext>,
-) -> Result<HttpResponse, Error>
-where
- Data: PerformCrud
- + SendActivity<Response = <Data as PerformCrud>::Response>
- + Clone
- + Deserialize<'a>
- + Send
- + 'static,
-{
- perform_crud::<Data>(data.0, context, apub_data).await
-}