Rewrite feature/lock post

This commit is contained in:
Felix Ableitner 2023-08-02 12:44:14 +02:00
parent 97fdc97cd9
commit a9e813dfc4
9 changed files with 172 additions and 204 deletions

View file

@ -6,9 +6,6 @@ set -e
export RUST_BACKTRACE=1
export RUST_LOG="warn,lemmy_server=debug,lemmy_api=debug,lemmy_api_common=debug,lemmy_api_crud=debug,lemmy_apub=debug,lemmy_db_schema=debug,lemmy_db_views=debug,lemmy_db_views_actor=debug,lemmy_db_views_moderator=debug,lemmy_routes=debug,lemmy_utils=debug,lemmy_websocket=debug"
echo "killall existing lemmy_server processes"
killall -s1 lemmy_server || true
for INSTANCE in lemmy_alpha lemmy_beta lemmy_gamma lemmy_delta lemmy_epsilon; do
echo "DB URL: ${LEMMY_DATABASE_URL} INSTANCE: $INSTANCE"
psql "${LEMMY_DATABASE_URL}/lemmy" -c "DROP DATABASE IF EXISTS $INSTANCE"

View file

@ -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

View file

@ -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,70 +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?;
Ok(
build_post_response(
context,
orig_post.community_id,
local_user_view.person.id,
post_id,
)
.await?
.0,
)
} 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
}

View file

@ -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,61 +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?;
Ok(
build_post_response(
context,
orig_post.community_id,
local_user_view.person.id,
post_id,
)
.await?
.0,
)
}
build_post_response(&context, orig_post.community_id, person_id, post_id).await
}

View file

@ -40,6 +40,8 @@ pub enum SendActivityData {
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),

View file

@ -24,7 +24,6 @@ use activitypub_federation::{
use lemmy_api_common::{
community::{AddModToCommunity, AddModToCommunityResponse},
context::LemmyContext,
post::{FeaturePost, PostResponse},
utils::{generate_featured_url, generate_moderators_url, local_user_view_from_jwt},
};
use lemmy_db_schema::{
@ -201,25 +200,20 @@ impl SendActivity for AddModToCommunity {
}
}
#[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
}
}

View file

@ -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,
traits::{ActivityHandler, Actor},
};
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(())
}

View file

@ -2,6 +2,7 @@ use self::following::send_follow_community;
use crate::{
activities::{
block::{send_ban_from_community, send_ban_from_site},
community::{collection_add::send_feature_post, lock_page::send_lock_post},
deletion::{
delete_user::delete_user,
send_apub_delete_in_community,
@ -263,6 +264,8 @@ pub async fn match_outgoing_activities(
)
.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) | UpdateComment(comment) => {
let creator_id = comment.creator_id;
CreateOrUpdateNote::send(comment, creator_id, CreateOrUpdateType::Create, context).await

View file

@ -8,7 +8,7 @@ use lemmy_api::{
},
community::{ban::ban_from_community, follow::follow_community},
local_user::{ban_person::ban_from_site, notifications::mark_reply_read::mark_reply_as_read},
post::like::like_post,
post::{feature::feature_post, like::like_post, lock::lock_post},
post_report::create::create_post_report,
Perform,
};
@ -42,15 +42,7 @@ use lemmy_api_common::{
SaveUserSettings,
VerifyEmail,
},
post::{
FeaturePost,
GetSiteMetadata,
ListPostReports,
LockPost,
MarkPostAsRead,
ResolvePostReport,
SavePost,
},
post::{GetSiteMetadata, ListPostReports, MarkPostAsRead, ResolvePostReport, SavePost},
private_message::{
CreatePrivateMessage,
CreatePrivateMessageReport,
@ -181,8 +173,8 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
"/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>))