mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-11-26 06:11:26 +00:00
Merge remote-tracking branch 'origin/main' into federation-send-parallel
This commit is contained in:
commit
c2dab71377
45 changed files with 455 additions and 369 deletions
18
Cargo.lock
generated
18
Cargo.lock
generated
|
@ -977,9 +977,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.7"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f"
|
||||
checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
"clap_derive",
|
||||
|
@ -987,9 +987,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.7"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f"
|
||||
checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
|
@ -999,9 +999,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "clap_derive"
|
||||
version = "4.5.5"
|
||||
version = "4.5.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6"
|
||||
checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
|
@ -3286,7 +3286,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.52.5",
|
||||
"windows-targets 0.48.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -5210,9 +5210,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.117"
|
||||
version = "1.0.120"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3"
|
||||
checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5"
|
||||
dependencies = [
|
||||
"indexmap 2.2.6",
|
||||
"itoa",
|
||||
|
|
|
@ -17,7 +17,11 @@ pub async fn distinguish_comment(
|
|||
context: Data<LemmyContext>,
|
||||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let orig_comment = CommentView::read(&mut context.pool(), data.comment_id, None)
|
||||
let orig_comment = CommentView::read(
|
||||
&mut context.pool(),
|
||||
data.comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
@ -54,7 +58,7 @@ pub async fn distinguish_comment(
|
|||
let comment_view = CommentView::read(
|
||||
&mut context.pool(),
|
||||
data.comment_id,
|
||||
Some(local_user_view.person.id),
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
|
|
@ -35,7 +35,11 @@ pub async fn like_comment(
|
|||
check_bot_account(&local_user_view.person)?;
|
||||
|
||||
let comment_id = data.comment_id;
|
||||
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
let orig_comment = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ pub async fn list_comment_likes(
|
|||
let comment_view = CommentView::read(
|
||||
&mut context.pool(),
|
||||
data.comment_id,
|
||||
Some(local_user_view.person.id),
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
|
|
@ -32,8 +32,11 @@ pub async fn save_comment(
|
|||
}
|
||||
|
||||
let comment_id = data.comment_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id))
|
||||
let comment_view = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -35,7 +35,11 @@ pub async fn create_comment_report(
|
|||
|
||||
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)
|
||||
let comment_view = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -50,8 +50,12 @@ pub async fn block_community(
|
|||
.with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?;
|
||||
}
|
||||
|
||||
let community_view =
|
||||
CommunityView::read(&mut context.pool(), community_id, Some(person_id), false)
|
||||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
Some(&local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindCommunity)?;
|
||||
|
||||
|
|
|
@ -62,9 +62,12 @@ pub async fn follow_community(
|
|||
}
|
||||
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_view =
|
||||
CommunityView::read(&mut context.pool(), community_id, Some(person_id), false)
|
||||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
Some(&local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindCommunity)?;
|
||||
|
||||
|
|
|
@ -76,9 +76,12 @@ pub async fn transfer_community(
|
|||
ModTransferCommunity::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let community_id = data.community_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let community_view =
|
||||
CommunityView::read(&mut context.pool(), community_id, Some(person_id), false)
|
||||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
Some(&local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindCommunity)?;
|
||||
|
||||
|
|
|
@ -72,11 +72,5 @@ pub async fn feature_post(
|
|||
)
|
||||
.await?;
|
||||
|
||||
build_post_response(
|
||||
&context,
|
||||
orig_post.community_id,
|
||||
&local_user_view.person,
|
||||
post_id,
|
||||
)
|
||||
.await
|
||||
build_post_response(&context, orig_post.community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -85,11 +85,5 @@ pub async fn like_post(
|
|||
)
|
||||
.await?;
|
||||
|
||||
build_post_response(
|
||||
context.deref(),
|
||||
post.community_id,
|
||||
&local_user_view.person,
|
||||
post_id,
|
||||
)
|
||||
.await
|
||||
build_post_response(context.deref(), post.community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -63,11 +63,5 @@ pub async fn lock_post(
|
|||
)
|
||||
.await?;
|
||||
|
||||
build_post_response(
|
||||
&context,
|
||||
orig_post.community_id,
|
||||
&local_user_view.person,
|
||||
post_id,
|
||||
)
|
||||
.await
|
||||
build_post_response(&context, orig_post.community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -34,7 +34,12 @@ pub async fn save_post(
|
|||
|
||||
let post_id = data.post_id;
|
||||
let person_id = local_user_view.person.id;
|
||||
let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), false)
|
||||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
post_id,
|
||||
Some(&local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindPost)?;
|
||||
|
||||
|
|
|
@ -29,7 +29,11 @@ pub async fn purge_comment(
|
|||
let comment_id = data.comment_id;
|
||||
|
||||
// Read the comment to get the post_id and community
|
||||
let comment_view = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
let comment_view = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -36,8 +36,8 @@ pub async fn build_comment_response(
|
|||
local_user_view: Option<LocalUserView>,
|
||||
recipient_ids: Vec<LocalUserId>,
|
||||
) -> LemmyResult<CommentResponse> {
|
||||
let person_id = local_user_view.map(|l| l.person.id);
|
||||
let comment_view = CommentView::read(&mut context.pool(), comment_id, person_id)
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
let comment_view = CommentView::read(&mut context.pool(), comment_id, local_user.as_ref())
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
Ok(CommentResponse {
|
||||
|
@ -54,11 +54,11 @@ pub async fn build_community_response(
|
|||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
let person_id = local_user_view.person.id;
|
||||
let local_user = local_user_view.local_user;
|
||||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
Some(person_id),
|
||||
Some(&local_user),
|
||||
is_mod_or_admin,
|
||||
)
|
||||
.await?
|
||||
|
@ -74,16 +74,17 @@ pub async fn build_community_response(
|
|||
pub async fn build_post_response(
|
||||
context: &LemmyContext,
|
||||
community_id: CommunityId,
|
||||
person: &Person,
|
||||
local_user_view: LocalUserView,
|
||||
post_id: PostId,
|
||||
) -> LemmyResult<Json<PostResponse>> {
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person, community_id)
|
||||
let local_user = local_user_view.local_user;
|
||||
let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id)
|
||||
.await
|
||||
.is_ok();
|
||||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
post_id,
|
||||
Some(person.id),
|
||||
Some(&local_user),
|
||||
is_mod_or_admin,
|
||||
)
|
||||
.await?
|
||||
|
@ -103,6 +104,7 @@ pub async fn send_local_notifs(
|
|||
let mut recipient_ids = Vec::new();
|
||||
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
|
||||
|
||||
// let person = my_local_user.person;
|
||||
// Read the comment view to get extra info
|
||||
let comment_view = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
.await?
|
||||
|
|
|
@ -8,20 +8,18 @@ use lemmy_api_common::{
|
|||
utils::{
|
||||
check_community_user_action,
|
||||
check_post_deleted_or_removed,
|
||||
generate_local_apub_endpoint,
|
||||
get_url_blocklist,
|
||||
is_mod_or_admin,
|
||||
local_site_to_slur_regex,
|
||||
process_markdown,
|
||||
update_read_comments,
|
||||
EndpointType,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
impls::actor_language::default_post_language,
|
||||
source::{
|
||||
actor_language::CommunityLanguage,
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm},
|
||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||
comment_reply::{CommentReply, CommentReplyUpdateForm},
|
||||
local_site::LocalSite,
|
||||
person_mention::{PersonMention, PersonMentionUpdateForm},
|
||||
|
@ -56,7 +54,7 @@ pub async fn create_comment(
|
|||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
post_id,
|
||||
Some(local_user_view.person.id),
|
||||
Some(&local_user_view.local_user),
|
||||
true,
|
||||
)
|
||||
.await?
|
||||
|
@ -126,25 +124,7 @@ pub async fn create_comment(
|
|||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
|
||||
|
||||
// Necessary to update the ap_id
|
||||
let inserted_comment_id = inserted_comment.id;
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
|
||||
let apub_id = generate_local_apub_endpoint(
|
||||
EndpointType::Comment,
|
||||
&inserted_comment_id.to_string(),
|
||||
&protocol_and_hostname,
|
||||
)?;
|
||||
let updated_comment = Comment::update(
|
||||
&mut context.pool(),
|
||||
inserted_comment_id,
|
||||
&CommentUpdateForm {
|
||||
ap_id: Some(apub_id),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreateComment)?;
|
||||
|
||||
// Scan the comment for user mentions, add those rows
|
||||
let mentions = scrape_text_for_mentions(&content);
|
||||
|
@ -170,7 +150,7 @@ pub async fn create_comment(
|
|||
.with_lemmy_type(LemmyErrorType::CouldntLikeComment)?;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
SendActivityData::CreateComment(updated_comment.clone()),
|
||||
SendActivityData::CreateComment(inserted_comment.clone()),
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
|
|
|
@ -21,7 +21,11 @@ pub async fn delete_comment(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let comment_id = data.comment_id;
|
||||
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
let orig_comment = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -25,7 +25,11 @@ pub async fn remove_comment(
|
|||
local_user_view: LocalUserView,
|
||||
) -> LemmyResult<Json<CommentResponse>> {
|
||||
let comment_id = data.comment_id;
|
||||
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
let orig_comment = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
@ -68,14 +72,8 @@ pub async fn remove_comment(
|
|||
};
|
||||
ModRemoveComment::create(&mut context.pool(), &form).await?;
|
||||
|
||||
let recipient_ids = send_local_notifs(
|
||||
vec![],
|
||||
comment_id,
|
||||
&local_user_view.person.clone(),
|
||||
false,
|
||||
&context,
|
||||
)
|
||||
.await?;
|
||||
let recipient_ids =
|
||||
send_local_notifs(vec![], comment_id, &local_user_view.person, false, &context).await?;
|
||||
let updated_comment_id = updated_comment.id;
|
||||
|
||||
ActivityChannel::submit_activity(
|
||||
|
|
|
@ -36,7 +36,11 @@ pub async fn update_comment(
|
|||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
|
||||
let comment_id = data.comment_id;
|
||||
let orig_comment = CommentView::read(&mut context.pool(), comment_id, None)
|
||||
let orig_comment = CommentView::read(
|
||||
&mut context.pool(),
|
||||
comment_id,
|
||||
Some(&local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
||||
|
|
|
@ -8,13 +8,11 @@ use lemmy_api_common::{
|
|||
send_activity::SendActivityData,
|
||||
utils::{
|
||||
check_community_user_action,
|
||||
generate_local_apub_endpoint,
|
||||
get_url_blocklist,
|
||||
honeypot_check,
|
||||
local_site_to_slur_regex,
|
||||
mark_post_as_read,
|
||||
process_markdown_opt,
|
||||
EndpointType,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
|
@ -23,7 +21,7 @@ use lemmy_db_schema::{
|
|||
actor_language::CommunityLanguage,
|
||||
community::Community,
|
||||
local_site::LocalSite,
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm, PostUpdateForm},
|
||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||
},
|
||||
traits::{Crud, Likeable},
|
||||
utils::diesel_url_create,
|
||||
|
@ -147,26 +145,8 @@ pub async fn create_post(
|
|||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreatePost)?;
|
||||
|
||||
let inserted_post_id = inserted_post.id;
|
||||
let protocol_and_hostname = context.settings().get_protocol_and_hostname();
|
||||
let apub_id = generate_local_apub_endpoint(
|
||||
EndpointType::Post,
|
||||
&inserted_post_id.to_string(),
|
||||
&protocol_and_hostname,
|
||||
)?;
|
||||
let updated_post = Post::update(
|
||||
&mut context.pool(),
|
||||
inserted_post_id,
|
||||
&PostUpdateForm {
|
||||
ap_id: Some(apub_id),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreatePost)?;
|
||||
|
||||
generate_post_link_metadata(
|
||||
updated_post.clone(),
|
||||
inserted_post.clone(),
|
||||
custom_thumbnail.map(Into::into),
|
||||
|post| Some(SendActivityData::CreatePost(post)),
|
||||
Some(local_site),
|
||||
|
@ -189,11 +169,11 @@ pub async fn create_post(
|
|||
|
||||
mark_post_as_read(person_id, post_id, &mut context.pool()).await?;
|
||||
|
||||
if let Some(url) = updated_post.url.clone() {
|
||||
if let Some(url) = inserted_post.url.clone() {
|
||||
if community.visibility == CommunityVisibility::Public {
|
||||
spawn_try_task(async move {
|
||||
let mut webmention =
|
||||
Webmention::new::<Url>(updated_post.ap_id.clone().into(), url.clone().into())?;
|
||||
Webmention::new::<Url>(inserted_post.ap_id.clone().into(), url.clone().into())?;
|
||||
webmention.set_checked(true);
|
||||
match webmention
|
||||
.send()
|
||||
|
@ -208,5 +188,5 @@ pub async fn create_post(
|
|||
}
|
||||
};
|
||||
|
||||
build_post_response(&context, community_id, &local_user_view.person, post_id).await
|
||||
build_post_response(&context, community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ pub async fn delete_post(
|
|||
build_post_response(
|
||||
&context,
|
||||
orig_post.community_id,
|
||||
&local_user_view.person,
|
||||
local_user_view,
|
||||
data.post_id,
|
||||
)
|
||||
.await
|
||||
|
|
|
@ -55,7 +55,13 @@ pub async fn get_post(
|
|||
.await
|
||||
.is_ok();
|
||||
|
||||
let post_view = PostView::read(&mut context.pool(), post_id, person_id, is_mod_or_admin)
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
let post_view = PostView::read(
|
||||
&mut context.pool(),
|
||||
post_id,
|
||||
local_user.as_ref(),
|
||||
is_mod_or_admin,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindPost)?;
|
||||
|
||||
|
@ -76,20 +82,19 @@ pub async fn get_post(
|
|||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
person_id,
|
||||
local_user.as_ref(),
|
||||
is_mod_or_admin,
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindCommunity)?;
|
||||
|
||||
let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).await?;
|
||||
let local_user = local_user_view.as_ref().map(|u| &u.local_user);
|
||||
|
||||
// Fetch the cross_posts
|
||||
let cross_posts = if let Some(url) = &post_view.post.url {
|
||||
let mut x_posts = PostQuery {
|
||||
url_search: Some(url.inner().as_str().into()),
|
||||
local_user,
|
||||
local_user: local_user.as_ref(),
|
||||
..Default::default()
|
||||
}
|
||||
.list(&local_site.site, &mut context.pool())
|
||||
|
|
|
@ -73,11 +73,5 @@ pub async fn remove_post(
|
|||
)
|
||||
.await?;
|
||||
|
||||
build_post_response(
|
||||
&context,
|
||||
orig_post.community_id,
|
||||
&local_user_view.person,
|
||||
post_id,
|
||||
)
|
||||
.await
|
||||
build_post_response(&context, orig_post.community_id, local_user_view, post_id).await
|
||||
}
|
||||
|
|
|
@ -137,7 +137,7 @@ pub async fn update_post(
|
|||
build_post_response(
|
||||
context.deref(),
|
||||
orig_post.community_id,
|
||||
&local_user_view.person,
|
||||
local_user_view,
|
||||
post_id,
|
||||
)
|
||||
.await
|
||||
|
|
|
@ -6,19 +6,17 @@ use lemmy_api_common::{
|
|||
send_activity::{ActivityChannel, SendActivityData},
|
||||
utils::{
|
||||
check_person_block,
|
||||
generate_local_apub_endpoint,
|
||||
get_interface_language,
|
||||
get_url_blocklist,
|
||||
local_site_to_slur_regex,
|
||||
process_markdown,
|
||||
send_email_to_user,
|
||||
EndpointType,
|
||||
},
|
||||
};
|
||||
use lemmy_db_schema::{
|
||||
source::{
|
||||
local_site::LocalSite,
|
||||
private_message::{PrivateMessage, PrivateMessageInsertForm, PrivateMessageUpdateForm},
|
||||
private_message::{PrivateMessage, PrivateMessageInsertForm},
|
||||
},
|
||||
traits::Crud,
|
||||
};
|
||||
|
@ -58,24 +56,6 @@ pub async fn create_private_message(
|
|||
.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 {
|
||||
ap_id: Some(apub_id),
|
||||
..Default::default()
|
||||
},
|
||||
)
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?;
|
||||
|
||||
let view = PrivateMessageView::read(&mut context.pool(), inserted_private_message.id)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindPrivateMessage)?;
|
||||
|
|
|
@ -29,7 +29,7 @@ pub async fn get_community(
|
|||
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
|
||||
let person_id = local_user_view.as_ref().map(|u| u.person.id);
|
||||
let local_user = local_user_view.as_ref().map(|u| &u.local_user);
|
||||
|
||||
let community_id = match data.id {
|
||||
Some(id) => id,
|
||||
|
@ -53,7 +53,7 @@ pub async fn get_community(
|
|||
let community_view = CommunityView::read(
|
||||
&mut context.pool(),
|
||||
community_id,
|
||||
person_id,
|
||||
local_user,
|
||||
is_mod_or_admin,
|
||||
)
|
||||
.await?
|
||||
|
|
|
@ -10,7 +10,7 @@ use lemmy_api_common::{
|
|||
site::{ResolveObject, ResolveObjectResponse},
|
||||
utils::check_private_instance,
|
||||
};
|
||||
use lemmy_db_schema::{newtypes::PersonId, source::local_site::LocalSite, utils::DbPool};
|
||||
use lemmy_db_schema::{source::local_site::LocalSite, utils::DbPool};
|
||||
use lemmy_db_views::structs::{CommentView, LocalUserView, PostView};
|
||||
use lemmy_db_views_actor::structs::{CommunityView, PersonView};
|
||||
use lemmy_utils::error::{LemmyErrorExt2, LemmyErrorType, LemmyResult};
|
||||
|
@ -23,10 +23,9 @@ pub async fn resolve_object(
|
|||
) -> LemmyResult<Json<ResolveObjectResponse>> {
|
||||
let local_site = LocalSite::read(&mut context.pool()).await?;
|
||||
check_private_instance(&local_user_view, &local_site)?;
|
||||
let person_id = local_user_view.map(|v| v.person.id);
|
||||
// If we get a valid personId back we can safely assume that the user is authenticated,
|
||||
// if there's no personId then the JWT was missing or invalid.
|
||||
let is_authenticated = person_id.is_some();
|
||||
let is_authenticated = local_user_view.is_some();
|
||||
|
||||
let res = if is_authenticated {
|
||||
// user is fully authenticated; allow remote lookups as well.
|
||||
|
@ -37,24 +36,26 @@ pub async fn resolve_object(
|
|||
}
|
||||
.with_lemmy_type(LemmyErrorType::CouldntFindObject)?;
|
||||
|
||||
convert_response(res, person_id, &mut context.pool())
|
||||
convert_response(res, local_user_view, &mut context.pool())
|
||||
.await
|
||||
.with_lemmy_type(LemmyErrorType::CouldntFindObject)
|
||||
}
|
||||
|
||||
async fn convert_response(
|
||||
object: SearchableObjects,
|
||||
user_id: Option<PersonId>,
|
||||
local_user_view: Option<LocalUserView>,
|
||||
pool: &mut DbPool<'_>,
|
||||
) -> LemmyResult<Json<ResolveObjectResponse>> {
|
||||
use SearchableObjects::*;
|
||||
let removed_or_deleted;
|
||||
let mut res = ResolveObjectResponse::default();
|
||||
let local_user = local_user_view.map(|l| l.local_user);
|
||||
|
||||
match object {
|
||||
Post(p) => {
|
||||
removed_or_deleted = p.deleted || p.removed;
|
||||
res.post = Some(
|
||||
PostView::read(pool, p.id, user_id, false)
|
||||
PostView::read(pool, p.id, local_user.as_ref(), false)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindPost)?,
|
||||
)
|
||||
|
@ -62,7 +63,7 @@ async fn convert_response(
|
|||
Comment(c) => {
|
||||
removed_or_deleted = c.deleted || c.removed;
|
||||
res.comment = Some(
|
||||
CommentView::read(pool, c.id, user_id)
|
||||
CommentView::read(pool, c.id, local_user.as_ref())
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?,
|
||||
)
|
||||
|
@ -79,7 +80,7 @@ async fn convert_response(
|
|||
UserOrCommunity::Community(c) => {
|
||||
removed_or_deleted = c.deleted || c.removed;
|
||||
res.community = Some(
|
||||
CommunityView::read(pool, c.id, user_id, false)
|
||||
CommunityView::read(pool, c.id, local_user.as_ref(), false)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindCommunity)?,
|
||||
)
|
||||
|
|
|
@ -564,6 +564,10 @@ BEGIN
|
|||
IF NOT (NEW.path ~ ('*.' || id)::lquery) THEN
|
||||
NEW.path = NEW.path || id;
|
||||
END IF;
|
||||
-- Set local ap_id
|
||||
IF NEW.local THEN
|
||||
NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/comment/' || id));
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
@ -573,3 +577,39 @@ CREATE TRIGGER change_values
|
|||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.comment_change_values ();
|
||||
|
||||
CREATE FUNCTION r.post_change_values ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
-- Set local ap_id
|
||||
IF NEW.local THEN
|
||||
NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/post/' || NEW.id::text));
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER change_values
|
||||
BEFORE INSERT ON post
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.post_change_values ();
|
||||
|
||||
CREATE FUNCTION r.private_message_change_values ()
|
||||
RETURNS TRIGGER
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
-- Set local ap_id
|
||||
IF NEW.local THEN
|
||||
NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/private_message/' || NEW.id::text));
|
||||
END IF;
|
||||
RETURN NEW;
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE TRIGGER change_values
|
||||
BEFORE INSERT ON private_message
|
||||
FOR EACH ROW
|
||||
EXECUTE FUNCTION r.private_message_change_values ();
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ CREATE FUNCTION r.controversy_rank (upvotes numeric, downvotes numeric)
|
|||
0
|
||||
ELSE
|
||||
(
|
||||
upvotes + downvotes) * CASE WHEN upvotes > downvotes THEN
|
||||
upvotes + downvotes) ^ CASE WHEN upvotes > downvotes THEN
|
||||
downvotes::float / upvotes::float
|
||||
ELSE
|
||||
upvotes::float / downvotes::float
|
||||
|
@ -57,6 +57,13 @@ BEGIN
|
|||
END;
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION r.local_url (url_path text)
|
||||
RETURNS text
|
||||
LANGUAGE sql
|
||||
STABLE PARALLEL SAFE RETURN (
|
||||
current_setting('lemmy.protocol_and_hostname') || url_path
|
||||
);
|
||||
|
||||
-- This function creates statement-level triggers for all operation types. It's designed this way
|
||||
-- because of these limitations:
|
||||
-- * A trigger that uses transition tables can only handle 1 operation type.
|
||||
|
|
|
@ -223,6 +223,7 @@ mod tests {
|
|||
use diesel_ltree::Ltree;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use url::Url;
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
|
@ -273,7 +274,12 @@ mod tests {
|
|||
path: Ltree(format!("0.{}", inserted_comment.id)),
|
||||
published: inserted_comment.published,
|
||||
updated: None,
|
||||
ap_id: inserted_comment.ap_id.clone(),
|
||||
ap_id: Url::parse(&format!(
|
||||
"https://lemmy-alpha/comment/{}",
|
||||
inserted_comment.id
|
||||
))
|
||||
.unwrap()
|
||||
.into(),
|
||||
distinguished: false,
|
||||
local: true,
|
||||
language_id: LanguageId::default(),
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
newtypes::{DbUrl, LanguageId, LocalUserId, PersonId},
|
||||
schema::{local_user, person, registration_application},
|
||||
schema::{community, local_user, person, registration_application},
|
||||
source::{
|
||||
actor_language::LocalUserLanguage,
|
||||
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||
|
@ -13,6 +13,7 @@ use crate::{
|
|||
now,
|
||||
DbPool,
|
||||
},
|
||||
CommunityVisibility,
|
||||
};
|
||||
use bcrypt::{hash, DEFAULT_COST};
|
||||
use diesel::{
|
||||
|
@ -225,6 +226,12 @@ pub trait LocalUserOptionHelper {
|
|||
fn show_read_posts(&self) -> bool;
|
||||
fn is_admin(&self) -> bool;
|
||||
fn show_nsfw(&self, site: &Site) -> bool;
|
||||
fn visible_communities_only<Q>(&self, query: Q) -> Q
|
||||
where
|
||||
Q: diesel::query_dsl::methods::FilterDsl<
|
||||
diesel::dsl::Eq<community::visibility, CommunityVisibility>,
|
||||
Output = Q,
|
||||
>;
|
||||
}
|
||||
|
||||
impl LocalUserOptionHelper for Option<&LocalUser> {
|
||||
|
@ -253,6 +260,20 @@ impl LocalUserOptionHelper for Option<&LocalUser> {
|
|||
.map(|l| l.show_nsfw)
|
||||
.unwrap_or(site.content_warning.is_some())
|
||||
}
|
||||
|
||||
fn visible_communities_only<Q>(&self, query: Q) -> Q
|
||||
where
|
||||
Q: diesel::query_dsl::methods::FilterDsl<
|
||||
diesel::dsl::Eq<community::visibility, CommunityVisibility>,
|
||||
Output = Q,
|
||||
>,
|
||||
{
|
||||
if self.is_none() {
|
||||
query.filter(community::visibility.eq(CommunityVisibility::Public))
|
||||
} else {
|
||||
query
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl LocalUserInsertForm {
|
||||
|
|
|
@ -390,6 +390,7 @@ mod tests {
|
|||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use std::collections::HashSet;
|
||||
use url::Url;
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
|
@ -447,7 +448,9 @@ mod tests {
|
|||
embed_description: None,
|
||||
embed_video_url: None,
|
||||
thumbnail_url: None,
|
||||
ap_id: inserted_post.ap_id.clone(),
|
||||
ap_id: Url::parse(&format!("https://lemmy-alpha/post/{}", inserted_post.id))
|
||||
.unwrap()
|
||||
.into(),
|
||||
local: true,
|
||||
language_id: Default::default(),
|
||||
featured_community: false,
|
||||
|
|
|
@ -100,6 +100,7 @@ mod tests {
|
|||
};
|
||||
use pretty_assertions::assert_eq;
|
||||
use serial_test::serial;
|
||||
use url::Url;
|
||||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
|
@ -138,7 +139,12 @@ mod tests {
|
|||
read: false,
|
||||
updated: None,
|
||||
published: inserted_private_message.published,
|
||||
ap_id: inserted_private_message.ap_id.clone(),
|
||||
ap_id: Url::parse(&format!(
|
||||
"https://lemmy-alpha/private_message/{}",
|
||||
inserted_private_message.id
|
||||
))
|
||||
.unwrap()
|
||||
.into(),
|
||||
local: true,
|
||||
};
|
||||
|
||||
|
|
|
@ -85,12 +85,6 @@ impl fmt::Display for PrivateMessageId {
|
|||
/// The person mention id.
|
||||
pub struct PersonMentionId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
/// The person block id.
|
||||
pub struct PersonBlockId(i32);
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)]
|
||||
#[cfg_attr(feature = "full", derive(DieselNewType, TS))]
|
||||
#[cfg_attr(feature = "full", ts(export))]
|
||||
|
|
|
@ -1,15 +1,7 @@
|
|||
use crate::{
|
||||
diesel::ExpressionMethods,
|
||||
newtypes::{DbUrl, PersonId},
|
||||
schema::community,
|
||||
CommentSortType,
|
||||
CommunityVisibility,
|
||||
SortType,
|
||||
};
|
||||
use crate::{newtypes::DbUrl, CommentSortType, SortType};
|
||||
use chrono::{DateTime, TimeDelta, Utc};
|
||||
use deadpool::Runtime;
|
||||
use diesel::{
|
||||
dsl,
|
||||
helper_types::AsExprOf,
|
||||
pg::Pg,
|
||||
query_builder::{Query, QueryFragment},
|
||||
|
@ -30,7 +22,8 @@ use diesel_async::{
|
|||
AsyncDieselConnectionManager,
|
||||
ManagerConfig,
|
||||
},
|
||||
SimpleAsyncConnection,
|
||||
AsyncConnection,
|
||||
RunQueryDsl,
|
||||
};
|
||||
use futures_util::{future::BoxFuture, Future, FutureExt};
|
||||
use i_love_jesus::CursorKey;
|
||||
|
@ -332,6 +325,8 @@ pub fn diesel_url_create(opt: Option<&str>) -> LemmyResult<Option<DbUrl>> {
|
|||
|
||||
fn establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConnection>> {
|
||||
let fut = async {
|
||||
// We only support TLS with sslmode=require currently
|
||||
let mut conn = if config.contains("sslmode=require") {
|
||||
rustls::crypto::ring::default_provider()
|
||||
.install_default()
|
||||
.expect("Failed to install rustls crypto provider");
|
||||
|
@ -351,13 +346,27 @@ fn establish_connection(config: &str) -> BoxFuture<ConnectionResult<AsyncPgConne
|
|||
error!("Database connection failed: {e}");
|
||||
}
|
||||
});
|
||||
let mut conn = AsyncPgConnection::try_from(client).await?;
|
||||
// * Change geqo_threshold back to default value if it was changed, so it's higher than the
|
||||
AsyncPgConnection::try_from(client).await?
|
||||
} else {
|
||||
AsyncPgConnection::establish(config).await?
|
||||
};
|
||||
|
||||
diesel::select((
|
||||
// Change geqo_threshold back to default value if it was changed, so it's higher than the
|
||||
// collapse limits
|
||||
// * Change collapse limits from 8 to 11 so the query planner can find a better table join order
|
||||
// for more complicated queries
|
||||
conn
|
||||
.batch_execute("SET geqo_threshold=12;SET from_collapse_limit=11;SET join_collapse_limit=11;")
|
||||
functions::set_config("geqo_threshold", "12", false),
|
||||
// Change collapse limits from 8 to 11 so the query planner can find a better table join
|
||||
// order for more complicated queries
|
||||
functions::set_config("from_collapse_limit", "11", false),
|
||||
functions::set_config("join_collapse_limit", "11", false),
|
||||
// Set `lemmy.protocol_and_hostname` so triggers can use it
|
||||
functions::set_config(
|
||||
"lemmy.protocol_and_hostname",
|
||||
SETTINGS.get_protocol_and_hostname(),
|
||||
false,
|
||||
),
|
||||
))
|
||||
.execute(&mut conn)
|
||||
.await
|
||||
.map_err(ConnectionError::CouldntSetupConfiguration)?;
|
||||
Ok(conn)
|
||||
|
@ -418,17 +427,11 @@ impl ServerCertVerifier for NoCertVerifier {
|
|||
|
||||
pub async fn build_db_pool() -> LemmyResult<ActualDbPool> {
|
||||
let db_url = SETTINGS.get_database_url();
|
||||
// We only support TLS with sslmode=require currently
|
||||
let tls_enabled = db_url.contains("sslmode=require");
|
||||
let manager = if tls_enabled {
|
||||
// diesel-async does not support any TLS connections out of the box, so we need to manually
|
||||
// provide a setup function which handles creating the connection
|
||||
let mut config = ManagerConfig::default();
|
||||
config.custom_setup = Box::new(establish_connection);
|
||||
AsyncDieselConnectionManager::<AsyncPgConnection>::new_with_config(&db_url, config)
|
||||
} else {
|
||||
AsyncDieselConnectionManager::<AsyncPgConnection>::new(&db_url)
|
||||
};
|
||||
let manager = AsyncDieselConnectionManager::<AsyncPgConnection>::new_with_config(&db_url, config);
|
||||
let pool = Pool::builder(manager)
|
||||
.max_size(SETTINGS.database.pool_size)
|
||||
.runtime(Runtime::Tokio1)
|
||||
|
@ -485,7 +488,7 @@ static EMAIL_REGEX: Lazy<Regex> = Lazy::new(|| {
|
|||
});
|
||||
|
||||
pub mod functions {
|
||||
use diesel::sql_types::{BigInt, Text, Timestamptz};
|
||||
use diesel::sql_types::{BigInt, Bool, Text, Timestamptz};
|
||||
|
||||
sql_function! {
|
||||
#[sql_name = "r.hot_rank"]
|
||||
|
@ -508,6 +511,8 @@ pub mod functions {
|
|||
|
||||
// really this function is variadic, this just adds the two-argument version
|
||||
sql_function!(fn coalesce<T: diesel::sql_types::SqlType + diesel::sql_types::SingleValue>(x: diesel::sql_types::Nullable<T>, y: T) -> T);
|
||||
|
||||
sql_function!(fn set_config(setting_name: Text, new_value: Text, is_local: Bool) -> Text);
|
||||
}
|
||||
|
||||
pub const DELETED_REPLACEMENT_TEXT: &str = "*Permanently Deleted*";
|
||||
|
@ -579,20 +584,6 @@ impl<RF, LF> Queries<RF, LF> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn visible_communities_only<Q>(my_person_id: Option<PersonId>, query: Q) -> Q
|
||||
where
|
||||
Q: diesel::query_dsl::methods::FilterDsl<
|
||||
dsl::Eq<community::visibility, CommunityVisibility>,
|
||||
Output = Q,
|
||||
>,
|
||||
{
|
||||
if my_person_id.is_none() {
|
||||
query.filter(community::visibility.eq(CommunityVisibility::Public))
|
||||
} else {
|
||||
query
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
#[allow(clippy::indexing_slicing)]
|
||||
mod tests {
|
||||
|
|
|
@ -36,22 +36,13 @@ use lemmy_db_schema::{
|
|||
post,
|
||||
},
|
||||
source::local_user::LocalUser,
|
||||
utils::{
|
||||
fuzzy_search,
|
||||
limit_and_offset,
|
||||
visible_communities_only,
|
||||
DbConn,
|
||||
DbPool,
|
||||
ListFn,
|
||||
Queries,
|
||||
ReadFn,
|
||||
},
|
||||
utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
|
||||
CommentSortType,
|
||||
ListingType,
|
||||
};
|
||||
|
||||
fn queries<'a>() -> Queries<
|
||||
impl ReadFn<'a, CommentView, (CommentId, Option<PersonId>)>,
|
||||
impl ReadFn<'a, CommentView, (CommentId, Option<&'a LocalUser>)>,
|
||||
impl ListFn<'a, CommentView, CommentQuery<'a>>,
|
||||
> {
|
||||
let is_creator_banned_from_community = exists(
|
||||
|
@ -182,9 +173,12 @@ fn queries<'a>() -> Queries<
|
|||
};
|
||||
|
||||
let read = move |mut conn: DbConn<'a>,
|
||||
(comment_id, my_person_id): (CommentId, Option<PersonId>)| async move {
|
||||
let mut query = all_joins(comment::table.find(comment_id).into_boxed(), my_person_id);
|
||||
query = visible_communities_only(my_person_id, query);
|
||||
(comment_id, my_local_user): (CommentId, Option<&'a LocalUser>)| async move {
|
||||
let mut query = all_joins(
|
||||
comment::table.find(comment_id).into_boxed(),
|
||||
my_local_user.person_id(),
|
||||
);
|
||||
query = my_local_user.visible_communities_only(query);
|
||||
query.first(&mut conn).await
|
||||
};
|
||||
|
||||
|
@ -301,7 +295,7 @@ fn queries<'a>() -> Queries<
|
|||
query = query.filter(not(is_creator_blocked(person_id_join)));
|
||||
};
|
||||
|
||||
query = visible_communities_only(options.local_user.person_id(), query);
|
||||
query = options.local_user.visible_communities_only(query);
|
||||
|
||||
// A Max depth given means its a tree fetch
|
||||
let (limit, offset) = if let Some(max_depth) = options.max_depth {
|
||||
|
@ -366,16 +360,16 @@ fn queries<'a>() -> Queries<
|
|||
}
|
||||
|
||||
impl CommentView {
|
||||
pub async fn read(
|
||||
pub async fn read<'a>(
|
||||
pool: &mut DbPool<'_>,
|
||||
comment_id: CommentId,
|
||||
my_person_id: Option<PersonId>,
|
||||
my_local_user: Option<&'a LocalUser>,
|
||||
) -> Result<Option<Self>, Error> {
|
||||
// If a person is given, then my_vote (res.9), if None, should be 0, not null
|
||||
// Necessary to differentiate between other person's votes
|
||||
if let Ok(Some(res)) = queries().read(pool, (comment_id, my_person_id)).await {
|
||||
if let Ok(Some(res)) = queries().read(pool, (comment_id, my_local_user)).await {
|
||||
let mut new_view = res.clone();
|
||||
if my_person_id.is_some() && res.my_vote.is_none() {
|
||||
if my_local_user.is_some() && res.my_vote.is_none() {
|
||||
new_view.my_vote = Some(0);
|
||||
}
|
||||
if res.comment.deleted || res.comment.removed {
|
||||
|
@ -676,7 +670,7 @@ mod tests {
|
|||
let read_comment_from_blocked_person = CommentView::read(
|
||||
pool,
|
||||
data.inserted_comment_1.id,
|
||||
Some(data.timmy_local_user_view.person.id),
|
||||
Some(&data.timmy_local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
@ -1171,7 +1165,7 @@ mod tests {
|
|||
let authenticated_comment = CommentView::read(
|
||||
pool,
|
||||
data.inserted_comment_0.id,
|
||||
Some(data.timmy_local_user_view.person.id),
|
||||
Some(&data.timmy_local_user_view.local_user),
|
||||
)
|
||||
.await;
|
||||
assert!(authenticated_comment.is_ok());
|
||||
|
@ -1211,7 +1205,7 @@ mod tests {
|
|||
let comment_view = CommentView::read(
|
||||
pool,
|
||||
data.inserted_comment_0.id,
|
||||
Some(inserted_banned_from_comm_local_user.person_id),
|
||||
Some(&inserted_banned_from_comm_local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
@ -1232,7 +1226,7 @@ mod tests {
|
|||
let comment_view = CommentView::read(
|
||||
pool,
|
||||
data.inserted_comment_0.id,
|
||||
Some(data.timmy_local_user_view.person.id),
|
||||
Some(&data.timmy_local_user_view.local_user),
|
||||
)
|
||||
.await?
|
||||
.ok_or(LemmyErrorType::CouldntFindComment)?;
|
||||
|
|
|
@ -49,7 +49,6 @@ use lemmy_db_schema::{
|
|||
get_conn,
|
||||
limit_and_offset,
|
||||
now,
|
||||
visible_communities_only,
|
||||
Commented,
|
||||
DbConn,
|
||||
DbPool,
|
||||
|
@ -64,7 +63,7 @@ use lemmy_db_schema::{
|
|||
use tracing::debug;
|
||||
|
||||
fn queries<'a>() -> Queries<
|
||||
impl ReadFn<'a, PostView, (PostId, Option<PersonId>, bool)>,
|
||||
impl ReadFn<'a, PostView, (PostId, Option<&'a LocalUser>, bool)>,
|
||||
impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>,
|
||||
> {
|
||||
let is_creator_banned_from_community = exists(
|
||||
|
@ -142,6 +141,7 @@ fn queries<'a>() -> Queries<
|
|||
.single_value()
|
||||
};
|
||||
|
||||
// TODO maybe this should go to localuser also
|
||||
let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>,
|
||||
my_person_id: Option<PersonId>| {
|
||||
let is_local_user_banned_from_community_selection: Box<
|
||||
|
@ -250,10 +250,14 @@ fn queries<'a>() -> Queries<
|
|||
))
|
||||
};
|
||||
|
||||
let read =
|
||||
move |mut conn: DbConn<'a>,
|
||||
(post_id, my_person_id, is_mod_or_admin): (PostId, Option<PersonId>, bool)| async move {
|
||||
let read = move |mut conn: DbConn<'a>,
|
||||
(post_id, my_local_user, is_mod_or_admin): (
|
||||
PostId,
|
||||
Option<&'a LocalUser>,
|
||||
bool,
|
||||
)| async move {
|
||||
// The left join below will return None in this case
|
||||
let my_person_id = my_local_user.person_id();
|
||||
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
|
||||
|
||||
let mut query = all_joins(
|
||||
|
@ -289,7 +293,7 @@ fn queries<'a>() -> Queries<
|
|||
);
|
||||
}
|
||||
|
||||
query = visible_communities_only(my_person_id, query);
|
||||
query = my_local_user.visible_communities_only(query);
|
||||
|
||||
Commented::new(query)
|
||||
.text("PostView::read")
|
||||
|
@ -437,7 +441,7 @@ fn queries<'a>() -> Queries<
|
|||
}
|
||||
};
|
||||
|
||||
query = visible_communities_only(options.local_user.person_id(), query);
|
||||
query = options.local_user.visible_communities_only(query);
|
||||
|
||||
// Dont filter blocks or missing languages for moderator view type
|
||||
if let (Some(person_id), false) = (
|
||||
|
@ -552,14 +556,14 @@ fn queries<'a>() -> Queries<
|
|||
}
|
||||
|
||||
impl PostView {
|
||||
pub async fn read(
|
||||
pub async fn read<'a>(
|
||||
pool: &mut DbPool<'_>,
|
||||
post_id: PostId,
|
||||
my_person_id: Option<PersonId>,
|
||||
my_local_user: Option<&'a LocalUser>,
|
||||
is_mod_or_admin: bool,
|
||||
) -> Result<Option<Self>, Error> {
|
||||
queries()
|
||||
.read(pool, (post_id, my_person_id, is_mod_or_admin))
|
||||
.read(pool, (post_id, my_local_user, is_mod_or_admin))
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
@ -938,7 +942,7 @@ mod tests {
|
|||
let post_listing_single_with_person = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(data.local_user_view.person.id),
|
||||
Some(&data.local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
|
@ -1067,7 +1071,7 @@ mod tests {
|
|||
let post_listing_single_with_person = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(data.local_user_view.person.id),
|
||||
Some(&data.local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
|
@ -1755,7 +1759,7 @@ mod tests {
|
|||
let authenticated_post = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(data.local_user_view.person.id),
|
||||
Some(&data.local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
|
@ -1797,7 +1801,7 @@ mod tests {
|
|||
let post_view = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(inserted_banned_from_comm_local_user.person_id),
|
||||
Some(&inserted_banned_from_comm_local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
|
@ -1819,7 +1823,7 @@ mod tests {
|
|||
let post_view = PostView::read(
|
||||
pool,
|
||||
data.inserted_post.id,
|
||||
Some(data.local_user_view.person.id),
|
||||
Some(&data.local_user_view.local_user),
|
||||
false,
|
||||
)
|
||||
.await?
|
||||
|
|
|
@ -22,27 +22,18 @@ use lemmy_db_schema::{
|
|||
instance_block,
|
||||
},
|
||||
source::{community::CommunityFollower, local_user::LocalUser, site::Site},
|
||||
utils::{
|
||||
fuzzy_search,
|
||||
limit_and_offset,
|
||||
visible_communities_only,
|
||||
DbConn,
|
||||
DbPool,
|
||||
ListFn,
|
||||
Queries,
|
||||
ReadFn,
|
||||
},
|
||||
utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn},
|
||||
ListingType,
|
||||
SortType,
|
||||
};
|
||||
|
||||
fn queries<'a>() -> Queries<
|
||||
impl ReadFn<'a, CommunityView, (CommunityId, Option<PersonId>, bool)>,
|
||||
impl ReadFn<'a, CommunityView, (CommunityId, Option<&'a LocalUser>, bool)>,
|
||||
impl ListFn<'a, CommunityView, (CommunityQuery<'a>, &'a Site)>,
|
||||
> {
|
||||
let all_joins = |query: community::BoxedQuery<'a, Pg>, my_person_id: Option<PersonId>| {
|
||||
let all_joins = |query: community::BoxedQuery<'a, Pg>, my_local_user: Option<&'a LocalUser>| {
|
||||
// The left join below will return None in this case
|
||||
let person_id_join = my_person_id.unwrap_or(PersonId(-1));
|
||||
let person_id_join = my_local_user.person_id().unwrap_or(PersonId(-1));
|
||||
|
||||
query
|
||||
.inner_join(community_aggregates::table)
|
||||
|
@ -89,14 +80,14 @@ fn queries<'a>() -> Queries<
|
|||
.and(community::deleted.eq(false));
|
||||
|
||||
let read = move |mut conn: DbConn<'a>,
|
||||
(community_id, my_person_id, is_mod_or_admin): (
|
||||
(community_id, my_local_user, is_mod_or_admin): (
|
||||
CommunityId,
|
||||
Option<PersonId>,
|
||||
Option<&'a LocalUser>,
|
||||
bool,
|
||||
)| async move {
|
||||
let mut query = all_joins(
|
||||
community::table.find(community_id).into_boxed(),
|
||||
my_person_id,
|
||||
my_local_user,
|
||||
)
|
||||
.select(selection);
|
||||
|
||||
|
@ -105,7 +96,7 @@ fn queries<'a>() -> Queries<
|
|||
query = query.filter(not_removed_or_deleted);
|
||||
}
|
||||
|
||||
query = visible_communities_only(my_person_id, query);
|
||||
query = my_local_user.visible_communities_only(query);
|
||||
|
||||
query.first(&mut conn).await
|
||||
};
|
||||
|
@ -116,11 +107,7 @@ fn queries<'a>() -> Queries<
|
|||
// The left join below will return None in this case
|
||||
let person_id_join = options.local_user.person_id().unwrap_or(PersonId(-1));
|
||||
|
||||
let mut query = all_joins(
|
||||
community::table.into_boxed(),
|
||||
options.local_user.person_id(),
|
||||
)
|
||||
.select(selection);
|
||||
let mut query = all_joins(community::table.into_boxed(), options.local_user).select(selection);
|
||||
|
||||
if let Some(search_term) = options.search_term {
|
||||
let searcher = fuzzy_search(&search_term);
|
||||
|
@ -173,7 +160,7 @@ fn queries<'a>() -> Queries<
|
|||
query = query.filter(community::nsfw.eq(false));
|
||||
}
|
||||
|
||||
query = visible_communities_only(options.local_user.person_id(), query);
|
||||
query = options.local_user.visible_communities_only(query);
|
||||
|
||||
let (limit, offset) = limit_and_offset(options.page, options.limit)?;
|
||||
query
|
||||
|
@ -187,14 +174,14 @@ fn queries<'a>() -> Queries<
|
|||
}
|
||||
|
||||
impl CommunityView {
|
||||
pub async fn read(
|
||||
pub async fn read<'a>(
|
||||
pool: &mut DbPool<'_>,
|
||||
community_id: CommunityId,
|
||||
my_person_id: Option<PersonId>,
|
||||
my_local_user: Option<&'a LocalUser>,
|
||||
is_mod_or_admin: bool,
|
||||
) -> Result<Option<Self>, Error> {
|
||||
queries()
|
||||
.read(pool, (community_id, my_person_id, is_mod_or_admin))
|
||||
.read(pool, (community_id, my_local_user, is_mod_or_admin))
|
||||
.await
|
||||
}
|
||||
|
||||
|
@ -388,7 +375,7 @@ mod tests {
|
|||
let authenticated_community = CommunityView::read(
|
||||
pool,
|
||||
data.inserted_community.id,
|
||||
Some(data.local_user.person_id),
|
||||
Some(&data.local_user),
|
||||
false,
|
||||
)
|
||||
.await;
|
||||
|
|
9
migrations/2024-06-24-000000_ap_id_triggers/down.sql
Normal file
9
migrations/2024-06-24-000000_ap_id_triggers/down.sql
Normal file
|
@ -0,0 +1,9 @@
|
|||
ALTER TABLE comment
|
||||
ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme ();
|
||||
|
||||
ALTER TABLE post
|
||||
ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme ();
|
||||
|
||||
ALTER TABLE private_message
|
||||
ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme ();
|
||||
|
9
migrations/2024-06-24-000000_ap_id_triggers/up.sql
Normal file
9
migrations/2024-06-24-000000_ap_id_triggers/up.sql
Normal file
|
@ -0,0 +1,9 @@
|
|||
ALTER TABLE comment
|
||||
ALTER COLUMN ap_id DROP DEFAULT;
|
||||
|
||||
ALTER TABLE post
|
||||
ALTER COLUMN ap_id DROP DEFAULT;
|
||||
|
||||
ALTER TABLE private_message
|
||||
ALTER COLUMN ap_id DROP DEFAULT;
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
UPDATE
|
||||
post_aggregates
|
||||
SET
|
||||
controversy_rank = CASE WHEN downvotes <= 0
|
||||
OR upvotes <= 0 THEN
|
||||
0
|
||||
ELSE
|
||||
(upvotes + downvotes) * CASE WHEN upvotes > downvotes THEN
|
||||
downvotes::float / upvotes::float
|
||||
ELSE
|
||||
upvotes::float / downvotes::float
|
||||
END
|
||||
END
|
||||
WHERE
|
||||
upvotes > 0
|
||||
AND downvotes > 0;
|
||||
|
17
migrations/2024-07-01-014711_exponential_controversy/up.sql
Normal file
17
migrations/2024-07-01-014711_exponential_controversy/up.sql
Normal file
|
@ -0,0 +1,17 @@
|
|||
UPDATE
|
||||
post_aggregates
|
||||
SET
|
||||
controversy_rank = CASE WHEN downvotes <= 0
|
||||
OR upvotes <= 0 THEN
|
||||
0
|
||||
ELSE
|
||||
(upvotes + downvotes) ^ CASE WHEN upvotes > downvotes THEN
|
||||
downvotes::float / upvotes::float
|
||||
ELSE
|
||||
upvotes::float / downvotes::float
|
||||
END
|
||||
END
|
||||
WHERE
|
||||
upvotes > 0
|
||||
AND downvotes > 0;
|
||||
|
|
@ -12,6 +12,6 @@ cargo +nightly fmt
|
|||
taplo format
|
||||
|
||||
# Format sql files
|
||||
find migrations -type f -name '*.sql' -exec pg_format -i {} +
|
||||
find migrations crates/db_schema/replaceable_schema -type f -name '*.sql' -exec pg_format -i {} +
|
||||
|
||||
cargo clippy --workspace --fix --allow-staged --allow-dirty --tests --all-targets --all-features -- -D warnings
|
||||
|
|
31
src/lib.rs
31
src/lib.rs
|
@ -55,7 +55,7 @@ use prometheus_metrics::serve_prometheus;
|
|||
use reqwest_middleware::ClientBuilder;
|
||||
use reqwest_tracing::TracingMiddleware;
|
||||
use serde_json::json;
|
||||
use std::{env, ops::Deref};
|
||||
use std::{env, ops::Deref, time::Duration};
|
||||
use tokio::signal::unix::SignalKind;
|
||||
use tracing::subscriber::set_global_default;
|
||||
use tracing_actix_web::TracingLogger;
|
||||
|
@ -64,6 +64,13 @@ use tracing_log::LogTracer;
|
|||
use tracing_subscriber::{filter::Targets, layer::SubscriberExt, Layer, Registry};
|
||||
use url::Url;
|
||||
|
||||
/// Timeout for HTTP requests while sending activities. A longer timeout provides better
|
||||
/// compatibility with other ActivityPub software that might allocate more time for synchronous
|
||||
/// processing of incoming activities. This timeout should be slightly longer than the time we
|
||||
/// expect a remote server to wait before aborting processing on its own to account for delays from
|
||||
/// establishing the HTTP connection and sending the request itself.
|
||||
const ACTIVITY_SENDING_TIMEOUT: Duration = Duration::from_secs(125);
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[command(
|
||||
version,
|
||||
|
@ -173,8 +180,8 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
serve_prometheus(prometheus, context.clone())?;
|
||||
}
|
||||
|
||||
let mut federation_config = FederationConfig::builder();
|
||||
federation_config
|
||||
let mut federation_config_builder = FederationConfig::builder();
|
||||
federation_config_builder
|
||||
.domain(SETTINGS.hostname.clone())
|
||||
.app_data(context.clone())
|
||||
.client(client.clone())
|
||||
|
@ -184,9 +191,9 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
.url_verifier(Box::new(VerifyUrlData(context.inner_pool().clone())));
|
||||
if local_site.federation_signed_fetch {
|
||||
let site: ApubSite = site_view.site.into();
|
||||
federation_config.signed_fetch_actor(&site);
|
||||
federation_config_builder.signed_fetch_actor(&site);
|
||||
}
|
||||
let federation_config = federation_config.build().await?;
|
||||
let federation_config = federation_config_builder.build().await?;
|
||||
|
||||
MATCH_OUTGOING_ACTIVITIES
|
||||
.set(Box::new(move |d, c| {
|
||||
|
@ -209,13 +216,23 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> {
|
|||
} else {
|
||||
None
|
||||
};
|
||||
let federate = (!args.disable_activity_sending).then(|| {
|
||||
|
||||
// This FederationConfig instance is exclusively used to send activities, so we can safely
|
||||
// increase the timeout without affecting timeouts for resolving objects anywhere.
|
||||
let federation_sender_config = if !args.disable_activity_sending {
|
||||
let mut federation_sender_config = federation_config_builder.clone();
|
||||
federation_sender_config.request_timeout(ACTIVITY_SENDING_TIMEOUT);
|
||||
Some(federation_sender_config.build().await?)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let federate = federation_sender_config.map(|cfg| {
|
||||
SendManager::run(
|
||||
Opts {
|
||||
process_index: args.federate_process_index,
|
||||
process_count: args.federate_process_count,
|
||||
},
|
||||
federation_config,
|
||||
cfg,
|
||||
SETTINGS.federation.clone(),
|
||||
)
|
||||
});
|
||||
|
|
|
@ -559,9 +559,9 @@ mod tests {
|
|||
|
||||
#[tokio::test]
|
||||
#[serial]
|
||||
async fn test_nodeinfo_voyager_lemmy_ml() -> LemmyResult<()> {
|
||||
async fn test_nodeinfo_lemmy_ml() -> LemmyResult<()> {
|
||||
let client = ClientBuilder::new(client_builder(&Settings::default()).build()?).build();
|
||||
let form = build_update_instance_form("voyager.lemmy.ml", &client)
|
||||
let form = build_update_instance_form("lemmy.ml", &client)
|
||||
.await
|
||||
.ok_or(LemmyErrorType::CouldntFindObject)?;
|
||||
assert_eq!(
|
||||
|
|
Loading…
Reference in a new issue