mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-26 03:11:08 +00:00
Rewrite remaining federation actions, get rid of PerformCrud trait (#3794)
* Rewrite ban actions * Rewrite delete/remove actions * Rewrite remove/delete community * Rewrite report actions * Rewrite feature/lock post * Rewrite update community actions * Rewrite remaining federation actions * Get rid of PerformCrud trait * clippy
This commit is contained in:
parent
be1389420b
commit
27be1efb74
46 changed files with 1699 additions and 1927 deletions
|
@ -30,9 +30,6 @@ else
|
|||
done
|
||||
fi
|
||||
|
||||
echo "killall existing lemmy_server processes"
|
||||
killall -s1 lemmy_server || true
|
||||
|
||||
echo "$PWD"
|
||||
|
||||
echo "start alpha"
|
||||
|
|
|
@ -7,12 +7,14 @@ pushd ..
|
|||
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
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
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,
|
||||
|
@ -21,55 +23,60 @@ use lemmy_db_views::structs::{CommentReportView, CommentView};
|
|||
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?;
|
||||
}
|
||||
|
||||
Ok(CommentReportResponse {
|
||||
comment_report_view,
|
||||
})
|
||||
// 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(Json(CommentReportResponse {
|
||||
comment_report_view,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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::{
|
||||
|
@ -15,58 +16,62 @@ 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)?;
|
||||
}
|
||||
|
||||
// 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),
|
||||
};
|
||||
|
||||
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?;
|
||||
|
||||
Ok(AddModToCommunityResponse { moderators })
|
||||
// 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)?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
|
||||
// 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(Json(AddModToCommunityResponse { moderators }))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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,
|
||||
|
@ -28,77 +29,85 @@ use lemmy_utils::{
|
|||
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)?;
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
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)?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
}
|
||||
|
||||
// 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_id = data.person_id;
|
||||
let person_view = PersonView::read(&mut context.pool(), person_id).await?;
|
||||
|
||||
Ok(BanFromCommunityResponse {
|
||||
person_view,
|
||||
banned: data.ban,
|
||||
})
|
||||
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)?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromCommunity(
|
||||
local_user_view.person,
|
||||
data.community_id,
|
||||
person_view.person.clone(),
|
||||
data.0.clone(),
|
||||
),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(BanFromCommunityResponse {
|
||||
person_view,
|
||||
banned: data.ban,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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::{
|
||||
|
@ -15,52 +16,56 @@ 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)?;
|
||||
}
|
||||
|
||||
let community_view =
|
||||
CommunityView::read(&mut context.pool(), community_id, Some(person_id), None).await?;
|
||||
|
||||
Ok(BlockCommunityResponse {
|
||||
blocked: data.block,
|
||||
community_view,
|
||||
})
|
||||
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?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::FollowCommunity(
|
||||
community_view.community.clone(),
|
||||
local_user_view.person.clone(),
|
||||
false,
|
||||
),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(BlockCommunityResponse {
|
||||
blocked: data.block,
|
||||
community_view,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -15,36 +16,38 @@ 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))]
|
||||
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)?;
|
||||
|
||||
#[tracing::instrument(skip(context))]
|
||||
async fn perform(&self, context: &Data<LemmyContext>) -> Result<CommunityResponse, LemmyError> {
|
||||
let data: &HideCommunity = self;
|
||||
let community_form = CommunityUpdateForm::builder()
|
||||
.hidden(Some(data.hidden))
|
||||
.build();
|
||||
|
||||
// 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 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_form = CommunityUpdateForm::builder()
|
||||
.hidden(Some(data.hidden))
|
||||
.build();
|
||||
let community_id = data.community_id;
|
||||
let community = Community::update(&mut context.pool(), community_id, &community_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateCommunityHiddenStatus)?;
|
||||
|
||||
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),
|
||||
};
|
||||
ModHideCommunity::create(&mut context.pool(), &mod_hide_community_form).await?;
|
||||
|
||||
let community_id = data.community_id;
|
||||
Community::update(&mut context.pool(), community_id, &community_form)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateCommunityHiddenStatus)?;
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
ModHideCommunity::create(&mut context.pool(), &mod_hide_community_form).await?;
|
||||
|
||||
build_community_response(context, local_user_view, community_id).await
|
||||
}
|
||||
build_community_response(&context, local_user_view, community_id).await
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
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;
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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::{
|
||||
|
@ -17,65 +18,68 @@ use lemmy_utils::{
|
|||
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)?;
|
||||
|
||||
// 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,
|
||||
};
|
||||
|
||||
ModBan::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let person_id = data.person_id;
|
||||
let person_view = PersonView::read(&mut context.pool(), person_id).await?;
|
||||
|
||||
Ok(BanPersonResponse {
|
||||
person_view,
|
||||
banned: data.ban,
|
||||
})
|
||||
.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,
|
||||
};
|
||||
|
||||
ModBan::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let person_view = PersonView::read(&mut context.pool(), data.person_id).await?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::BanFromSite(
|
||||
local_user_view.person,
|
||||
person_view.person.clone(),
|
||||
data.0.clone(),
|
||||
),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(BanPersonResponse {
|
||||
person_view,
|
||||
banned: data.ban,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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,
|
||||
|
@ -22,67 +23,65 @@ use lemmy_db_schema::{
|
|||
};
|
||||
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?;
|
||||
|
||||
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()
|
||||
};
|
||||
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,
|
||||
};
|
||||
|
||||
ModFeaturePost::create(&mut context.pool(), &form).await?;
|
||||
|
||||
build_post_response(
|
||||
context,
|
||||
orig_post.community_id,
|
||||
local_user_view.person.id,
|
||||
post_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?;
|
||||
|
||||
// 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?;
|
||||
|
||||
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, person_id, post_id).await
|
||||
}
|
||||
|
|
|
@ -80,13 +80,11 @@ pub async fn like_post(
|
|||
)
|
||||
.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
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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,
|
||||
|
@ -20,58 +21,56 @@ use lemmy_db_schema::{
|
|||
};
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
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,
|
||||
|
@ -21,51 +23,59 @@ use lemmy_db_views::structs::{PostReportView, PostView};
|
|||
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?;
|
||||
}
|
||||
|
||||
Ok(PostReportResponse { post_report_view })
|
||||
// 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(Json(PostReportResponse { post_report_view }))
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
mod create;
|
||||
mod list;
|
||||
mod resolve;
|
||||
pub mod create;
|
||||
pub mod list;
|
||||
pub mod resolve;
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::{
|
|||
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::{
|
||||
|
@ -39,10 +39,10 @@ pub async fn build_comment_response(
|
|||
}
|
||||
|
||||
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
|
||||
|
@ -57,10 +57,10 @@ pub async fn build_community_response(
|
|||
.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(
|
||||
|
@ -68,7 +68,7 @@ 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();
|
||||
|
@ -79,7 +79,7 @@ pub async fn build_post_response(
|
|||
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
|
||||
|
|
|
@ -1,10 +1,22 @@
|
|||
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::{
|
||||
|
@ -15,6 +27,7 @@ use tokio::{
|
|||
},
|
||||
task::JoinHandle,
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
type MatchOutgoingActivitiesBoxed =
|
||||
Box<for<'a> fn(SendActivityData, &'a Data<LemmyContext>) -> BoxFuture<'a, LemmyResult<()>>>;
|
||||
|
@ -26,12 +39,27 @@ pub static MATCH_OUTGOING_ACTIVITIES: OnceCell<MatchOutgoingActivitiesBoxed> = O
|
|||
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
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
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},
|
||||
|
@ -42,107 +41,104 @@ use lemmy_utils::{
|
|||
},
|
||||
};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for CreateCommunity {
|
||||
type Response = CommunityResponse;
|
||||
#[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;
|
||||
|
||||
#[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)?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
}
|
||||
|
||||
build_community_response(context, local_user_view, community_id).await
|
||||
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)?;
|
||||
}
|
||||
|
||||
// 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?;
|
||||
}
|
||||
|
||||
build_community_response(&context, local_user_view, community_id).await
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -13,36 +14,39 @@ 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
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -18,42 +19,50 @@ use lemmy_utils::{
|
|||
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
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -22,65 +23,68 @@ use lemmy_utils::{
|
|||
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)?;
|
||||
}
|
||||
|
||||
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_id = data.community_id;
|
||||
Community::update(&mut context.pool(), community_id, &community_form)
|
||||
// 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
|
||||
.with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?;
|
||||
|
||||
build_community_response(context, local_user_view, 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_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)?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::UpdateCommunity(local_user_view.person.clone(), community),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
build_community_response(&context, local_user_view, community_id).await
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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},
|
||||
|
@ -13,41 +13,38 @@ use lemmy_db_schema::source::{
|
|||
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 }))
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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},
|
||||
|
@ -8,24 +8,18 @@ use lemmy_api_common::{
|
|||
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,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,3 +1,3 @@
|
|||
mod create;
|
||||
mod delete;
|
||||
mod update;
|
||||
pub mod create;
|
||||
pub mod delete;
|
||||
pub mod update;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
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},
|
||||
|
@ -13,40 +13,37 @@ use lemmy_db_schema::source::{
|
|||
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 }))
|
||||
}
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
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;
|
||||
|
@ -9,10 +5,3 @@ pub mod post;
|
|||
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>;
|
||||
}
|
||||
|
|
|
@ -194,7 +194,5 @@ pub async fn create_post(
|
|||
}
|
||||
};
|
||||
|
||||
Ok(Json(
|
||||
build_post_response(&context, community_id, person_id, post_id).await?,
|
||||
))
|
||||
build_post_response(&context, community_id, person_id, post_id).await
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -12,52 +13,50 @@ 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))]
|
||||
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?;
|
||||
|
||||
#[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?;
|
||||
|
||||
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
|
||||
// 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
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
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::{
|
||||
|
@ -15,58 +16,56 @@ 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
|
||||
}
|
||||
|
|
|
@ -113,13 +113,11 @@ pub async fn update_post(
|
|||
|
||||
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
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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,
|
||||
|
@ -27,78 +28,77 @@ use lemmy_utils::{
|
|||
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,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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::{
|
||||
|
@ -12,42 +13,41 @@ 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)?;
|
||||
}
|
||||
|
||||
// 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)?;
|
||||
|
||||
let view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
|
||||
Ok(PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
})
|
||||
// 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)?;
|
||||
|
||||
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(Json(PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
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::{
|
||||
|
@ -19,48 +20,47 @@ use lemmy_utils::{
|
|||
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)?;
|
||||
}
|
||||
|
||||
// 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 view = PrivateMessageView::read(&mut context.pool(), private_message_id).await?;
|
||||
|
||||
Ok(PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
})
|
||||
// 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)?;
|
||||
|
||||
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?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::UpdatePrivateMessage(view.clone()),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(Json(PrivateMessageResponse {
|
||||
private_message_view: view,
|
||||
}))
|
||||
}
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
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},
|
||||
|
@ -38,177 +37,173 @@ use lemmy_utils::{
|
|||
},
|
||||
};
|
||||
|
||||
#[async_trait::async_trait(?Send)]
|
||||
impl PerformCrud for Register {
|
||||
type Response = LoginResponse;
|
||||
#[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;
|
||||
|
||||
#[tracing::instrument(skip(self, context))]
|
||||
async fn perform(&self, context: &Data<LemmyContext>) -> Result<LoginResponse, LemmyError> {
|
||||
let data: &Register = self;
|
||||
if local_site.registration_mode == RegistrationMode::Closed {
|
||||
return Err(LemmyErrorType::RegistrationClosed)?;
|
||||
}
|
||||
|
||||
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;
|
||||
password_length_check(&data.password)?;
|
||||
honeypot_check(&data.honeypot)?;
|
||||
|
||||
if local_site.registration_mode == RegistrationMode::Closed {
|
||||
return Err(LemmyErrorType::RegistrationClosed)?;
|
||||
}
|
||||
if local_site.require_email_verification && data.email.is_none() {
|
||||
return Err(LemmyErrorType::EmailRequired)?;
|
||||
}
|
||||
|
||||
password_length_check(&data.password)?;
|
||||
honeypot_check(&data.honeypot)?;
|
||||
if local_site.site_setup && require_registration_application && data.answer.is_none() {
|
||||
return Err(LemmyErrorType::RegistrationApplicationAnswerRequired)?;
|
||||
}
|
||||
|
||||
if local_site.require_email_verification && data.email.is_none() {
|
||||
return Err(LemmyErrorType::EmailRequired)?;
|
||||
}
|
||||
// Make sure passwords match
|
||||
if data.password != data.password_verify {
|
||||
return Err(LemmyErrorType::PasswordsDoNotMatch)?;
|
||||
}
|
||||
|
||||
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)?;
|
||||
}
|
||||
|
||||
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 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(),
|
||||
)?;
|
||||
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)?;
|
||||
}
|
||||
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
|
||||
// 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();
|
||||
// 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)?;
|
||||
// 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);
|
||||
// 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();
|
||||
// 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?;
|
||||
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 mut login_response = LoginResponse {
|
||||
jwt: None,
|
||||
registration_created: false,
|
||||
verify_email_sent: false,
|
||||
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");
|
||||
RegistrationApplication::create(&mut context.pool(), &form).await?;
|
||||
}
|
||||
|
||||
send_verification_email(
|
||||
&local_user_view,
|
||||
&email,
|
||||
&mut context.pool(),
|
||||
context.settings(),
|
||||
)
|
||||
.await?;
|
||||
login_response.verify_email_sent = true;
|
||||
}
|
||||
// Email the admins
|
||||
if local_site.application_email_admins {
|
||||
send_new_applicant_email_to_admins(&data.username, &mut context.pool(), context.settings())
|
||||
.await?;
|
||||
}
|
||||
|
||||
if require_registration_application {
|
||||
login_response.registration_created = true;
|
||||
}
|
||||
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))
|
||||
}
|
||||
|
|
|
@ -1,32 +1,36 @@
|
|||
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)?;
|
||||
}
|
||||
|
||||
Ok(DeleteAccountResponse {})
|
||||
// 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(Json(DeleteAccountResponse {}))
|
||||
}
|
||||
|
|
|
@ -1,2 +1,2 @@
|
|||
mod create;
|
||||
mod delete;
|
||||
pub mod create;
|
||||
pub mod delete;
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
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,
|
||||
|
@ -12,19 +11,18 @@ use activitypub_federation::{
|
|||
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;
|
||||
|
||||
|
@ -132,87 +130,74 @@ async fn generate_cc(
|
|||
})
|
||||
}
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl SendActivity for BanPerson {
|
||||
type Response = BanPersonResponse;
|
||||
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);
|
||||
|
||||
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 {
|
||||
// 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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,6 @@ use crate::{
|
|||
activities::community::{collection_add::CollectionAdd, collection_remove::CollectionRemove},
|
||||
InCommunity,
|
||||
},
|
||||
SendActivity,
|
||||
};
|
||||
use activitypub_federation::{
|
||||
config::Data,
|
||||
|
@ -22,13 +21,12 @@ use activitypub_federation::{
|
|||
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},
|
||||
|
@ -165,61 +163,41 @@ impl ActivityHandler for CollectionAdd {
|
|||
}
|
||||
}
|
||||
|
||||
#[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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,25 +9,23 @@ use crate::{
|
|||
},
|
||||
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,
|
||||
|
@ -102,59 +100,47 @@ impl ActivityHandler for UndoLockPage {
|
|||
}
|
||||
}
|
||||
|
||||
#[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(())
|
||||
}
|
||||
|
|
|
@ -4,7 +4,6 @@ use crate::{
|
|||
objects::{community::ApubCommunity, person::ApubPerson},
|
||||
protocol::{activities::community::report::Report, InCommunity},
|
||||
PostOrComment,
|
||||
SendActivity,
|
||||
};
|
||||
use activitypub_federation::{
|
||||
config::Data,
|
||||
|
@ -12,15 +11,12 @@ use activitypub_federation::{
|
|||
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,
|
||||
|
@ -28,58 +24,17 @@ use lemmy_db_schema::{
|
|||
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(),
|
||||
|
@ -96,7 +51,7 @@ impl Report {
|
|||
};
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -10,61 +10,43 @@ use crate::{
|
|||
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;
|
||||
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()),
|
||||
};
|
||||
|
||||
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()),
|
||||
};
|
||||
|
||||
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]
|
||||
|
@ -101,18 +83,3 @@ impl ActivityHandler for UpdateCommunity {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,92 +6,40 @@ use crate::{
|
|||
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;
|
||||
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::Create,
|
||||
context,
|
||||
)
|
||||
.await
|
||||
}
|
||||
}
|
||||
#[async_trait::async_trait]
|
||||
impl SendActivity for EditPrivateMessage {
|
||||
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::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]
|
||||
|
|
|
@ -3,7 +3,6 @@ use crate::{
|
|||
insert_received_activity,
|
||||
objects::{instance::remote_instance_inboxes, person::ApubPerson},
|
||||
protocol::activities::deletion::delete_user::DeleteUser,
|
||||
SendActivity,
|
||||
};
|
||||
use activitypub_federation::{
|
||||
config::Data,
|
||||
|
@ -11,50 +10,37 @@ use activitypub_federation::{
|
|||
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;
|
||||
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?;
|
||||
|
||||
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?;
|
||||
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
|
||||
|
|
|
@ -19,7 +19,6 @@ use crate::{
|
|||
activities::deletion::{delete::Delete, undo_delete::UndoDelete},
|
||||
InCommunity,
|
||||
},
|
||||
SendActivity,
|
||||
};
|
||||
use activitypub_federation::{
|
||||
config::Data,
|
||||
|
@ -28,14 +27,9 @@ use activitypub_federation::{
|
|||
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},
|
||||
|
@ -53,122 +47,6 @@ pub mod delete;
|
|||
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)]
|
||||
|
@ -200,12 +78,44 @@ pub(crate) async fn send_apub_delete_in_community(
|
|||
.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)]
|
||||
async fn send_apub_delete_private_message(
|
||||
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)]
|
||||
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)
|
||||
|
@ -215,11 +125,11 @@ async fn send_apub_delete_private_message(
|
|||
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(())
|
||||
}
|
||||
|
|
|
@ -8,12 +8,7 @@ use crate::{
|
|||
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,
|
||||
|
@ -21,17 +16,13 @@ use activitypub_federation::{
|
|||
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;
|
||||
|
@ -128,18 +119,3 @@ impl ActivityHandler for Follow {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,25 @@
|
|||
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,
|
||||
},
|
||||
|
@ -229,14 +243,46 @@ pub async fn match_outgoing_activities(
|
|||
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());
|
||||
|
@ -251,9 +297,46 @@ pub async fn match_outgoing_activities(
|
|||
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 {
|
||||
|
|
|
@ -1,33 +1,30 @@
|
|||
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,
|
||||
|
@ -39,27 +36,12 @@ use lemmy_api_common::{
|
|||
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,
|
||||
|
@ -85,11 +67,33 @@ use lemmy_api_crud::{
|
|||
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::{
|
||||
|
@ -137,29 +141,23 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
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")
|
||||
|
@ -179,18 +177,18 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.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>),
|
||||
|
@ -221,7 +219,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.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)),
|
||||
)
|
||||
|
@ -230,12 +228,9 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
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>),
|
||||
|
@ -260,7 +255,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
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
|
||||
|
@ -280,15 +275,12 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
)
|
||||
.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>),
|
||||
|
@ -343,12 +335,9 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
|||
.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)),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -408,43 +397,3 @@ where
|
|||
{
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue