-use crate::structs::CommentView;
+use crate::structs::{CommentView, LocalUserView};
use diesel::{
result::Error,
BoolExpressionMethods,
source::{
comment::{Comment, CommentSaved},
community::{Community, CommunityFollower, CommunityPersonBan},
- local_user::LocalUser,
person::Person,
person_block::PersonBlock,
post::Post,
CommentSortType,
ListingType,
};
-use typed_builder::TypedBuilder;
type CommentViewTuple = (
Comment,
}
}
-#[derive(TypedBuilder)]
-#[builder(field_defaults(default))]
-pub struct CommentQuery<'a, 'b: 'a> {
- #[builder(!default)]
- pool: &'a mut DbPool<'b>,
- listing_type: Option<ListingType>,
- sort: Option<CommentSortType>,
- community_id: Option<CommunityId>,
- post_id: Option<PostId>,
- parent_path: Option<Ltree>,
- creator_id: Option<PersonId>,
- local_user: Option<&'a LocalUser>,
- search_term: Option<String>,
- saved_only: Option<bool>,
- show_deleted_and_removed: Option<bool>,
- page: Option<i64>,
- limit: Option<i64>,
- max_depth: Option<i32>,
+#[derive(Default)]
+pub struct CommentQuery<'a> {
+ pub listing_type: Option<ListingType>,
+ pub sort: Option<CommentSortType>,
+ pub community_id: Option<CommunityId>,
+ pub post_id: Option<PostId>,
+ pub parent_path: Option<Ltree>,
+ pub creator_id: Option<PersonId>,
+ pub local_user: Option<&'a LocalUserView>,
+ pub search_term: Option<String>,
+ pub saved_only: Option<bool>,
+ pub is_profile_view: Option<bool>,
+ pub show_deleted_and_removed: Option<bool>,
+ pub page: Option<i64>,
+ pub limit: Option<i64>,
+ pub max_depth: Option<i32>,
}
-impl<'a, 'b: 'a> CommentQuery<'a, 'b> {
- pub async fn list(self) -> Result<Vec<CommentView>, Error> {
- let conn = &mut get_conn(self.pool).await?;
+impl<'a> CommentQuery<'a> {
+ pub async fn list(self, pool: &mut DbPool<'_>) -> Result<Vec<CommentView>, Error> {
+ let conn = &mut get_conn(pool).await?;
// The left join below will return None in this case
- let person_id_join = self.local_user.map(|l| l.person_id).unwrap_or(PersonId(-1));
- let local_user_id_join = self.local_user.map(|l| l.id).unwrap_or(LocalUserId(-1));
+ let person_id_join = self.local_user.map(|l| l.person.id).unwrap_or(PersonId(-1));
+ let local_user_id_join = self
+ .local_user
+ .map(|l| l.local_user.id)
+ .unwrap_or(LocalUserId(-1));
let mut query = comment::table
.inner_join(person::table)
query = query.filter(comment_saved::comment_id.is_not_null());
}
- if !self.show_deleted_and_removed.unwrap_or(true) {
+ let is_profile_view = self.is_profile_view.unwrap_or(false);
+ let is_creator = self.creator_id == self.local_user.map(|l| l.person.id);
+ // only show deleted comments to creator
+ if !is_creator {
query = query.filter(comment::deleted.eq(false));
+ }
+
+ let is_admin = self.local_user.map(|l| l.person.admin).unwrap_or(false);
+ // only show removed comments to admin when viewing user profile
+ if !(is_profile_view && is_admin) {
query = query.filter(comment::removed.eq(false));
}
- if !self.local_user.map(|l| l.show_bot_accounts).unwrap_or(true) {
+ if !self
+ .local_user
+ .map(|l| l.local_user.show_bot_accounts)
+ .unwrap_or(true)
+ {
query = query.filter(person::bot_account.eq(false));
};
};
query = match self.sort.unwrap_or(CommentSortType::Hot) {
- CommentSortType::Hot => query.then_order_by(comment_aggregates::hot_rank.desc()),
+ CommentSortType::Hot => query
+ .then_order_by(comment_aggregates::hot_rank.desc())
+ .then_order_by(comment_aggregates::published.desc()),
+ CommentSortType::Top => query
+ .order_by(comment_aggregates::score.desc())
+ .then_order_by(comment_aggregates::published.desc()),
CommentSortType::New => query.then_order_by(comment::published.desc()),
CommentSortType::Old => query.then_order_by(comment::published.asc()),
- CommentSortType::Top => query.order_by(comment_aggregates::score.desc()),
};
// Note: deleted and removed comments are done on the front side
#[cfg(test)]
mod tests {
- use crate::comment_view::{
- Comment,
- CommentQuery,
- CommentSortType,
- CommentView,
- Community,
- DbPool,
- LocalUser,
- Person,
- PersonBlock,
- Post,
+ #![allow(clippy::unwrap_used)]
+ #![allow(clippy::indexing_slicing)]
+
+ use crate::{
+ comment_view::{
+ Comment,
+ CommentQuery,
+ CommentSortType,
+ CommentView,
+ Community,
+ DbPool,
+ Person,
+ PersonBlock,
+ Post,
+ },
+ structs::LocalUserView,
};
use lemmy_db_schema::{
aggregates::structs::CommentAggregates,
community::CommunityInsertForm,
instance::Instance,
language::Language,
- local_user::LocalUserInsertForm,
+ local_user::{LocalUser, LocalUserInsertForm},
person::PersonInsertForm,
person_block::PersonBlockForm,
post::PostInsertForm,
inserted_comment_1: Comment,
inserted_comment_2: Comment,
inserted_post: Post,
- inserted_person: Person,
- inserted_local_user: LocalUser,
+ local_user_view: LocalUserView,
inserted_person_2: Person,
inserted_community: Community,
}
let _inserted_comment_like = CommentLike::like(pool, &comment_like_form).await.unwrap();
+ let local_user_view = LocalUserView {
+ local_user: inserted_local_user.clone(),
+ person: inserted_person.clone(),
+ counts: Default::default(),
+ };
Data {
inserted_instance,
inserted_comment_0,
inserted_comment_1,
inserted_comment_2,
inserted_post,
- inserted_person,
- inserted_local_user,
+ local_user_view,
inserted_person_2,
inserted_community,
}
let mut expected_comment_view_with_person = expected_comment_view_no_person.clone();
expected_comment_view_with_person.my_vote = Some(1);
- let read_comment_views_no_person = CommentQuery::builder()
- .pool(pool)
- .sort(Some(CommentSortType::Old))
- .post_id(Some(data.inserted_post.id))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_no_person = CommentQuery {
+ sort: (Some(CommentSortType::Old)),
+ post_id: (Some(data.inserted_post.id)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
assert_eq!(
expected_comment_view_no_person,
read_comment_views_no_person[0]
);
- let read_comment_views_with_person = CommentQuery::builder()
- .pool(pool)
- .sort(Some(CommentSortType::Old))
- .post_id(Some(data.inserted_post.id))
- .local_user(Some(&data.inserted_local_user))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_with_person = CommentQuery {
+ sort: (Some(CommentSortType::Old)),
+ post_id: (Some(data.inserted_post.id)),
+ local_user: (Some(&data.local_user_view)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
assert_eq!(
expected_comment_view_with_person,
let read_comment_from_blocked_person = CommentView::read(
pool,
data.inserted_comment_1.id,
- Some(data.inserted_person.id),
+ Some(data.local_user_view.person.id),
)
.await
.unwrap();
let data = init_data(pool).await;
let top_path = data.inserted_comment_0.path.clone();
- let read_comment_views_top_path = CommentQuery::builder()
- .pool(pool)
- .post_id(Some(data.inserted_post.id))
- .parent_path(Some(top_path))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_top_path = CommentQuery {
+ post_id: (Some(data.inserted_post.id)),
+ parent_path: (Some(top_path)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
let child_path = data.inserted_comment_1.path.clone();
- let read_comment_views_child_path = CommentQuery::builder()
- .pool(pool)
- .post_id(Some(data.inserted_post.id))
- .parent_path(Some(child_path))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_child_path = CommentQuery {
+ post_id: (Some(data.inserted_post.id)),
+ parent_path: (Some(child_path)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
// Make sure the comment parent-limited fetch is correct
assert_eq!(6, read_comment_views_top_path.len());
assert!(child_comments.contains(&data.inserted_comment_1));
assert!(!child_comments.contains(&data.inserted_comment_2));
- let read_comment_views_top_max_depth = CommentQuery::builder()
- .pool(pool)
- .post_id(Some(data.inserted_post.id))
- .max_depth(Some(1))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_top_max_depth = CommentQuery {
+ post_id: (Some(data.inserted_post.id)),
+ max_depth: (Some(1)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
// Make sure a depth limited one only has the top comment
assert_eq!(
assert_eq!(1, read_comment_views_top_max_depth.len());
let child_path = data.inserted_comment_1.path.clone();
- let read_comment_views_parent_max_depth = CommentQuery::builder()
- .pool(pool)
- .post_id(Some(data.inserted_post.id))
- .parent_path(Some(child_path))
- .max_depth(Some(1))
- .sort(Some(CommentSortType::New))
- .build()
- .list()
- .await
- .unwrap();
+ let read_comment_views_parent_max_depth = CommentQuery {
+ post_id: (Some(data.inserted_post.id)),
+ parent_path: (Some(child_path)),
+ max_depth: (Some(1)),
+ sort: (Some(CommentSortType::New)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
// Make sure a depth limited one, and given child comment 1, has 3
assert!(read_comment_views_parent_max_depth[2]
// by default, user has all languages enabled and should see all comments
// (except from blocked user)
- let all_languages = CommentQuery::builder()
- .pool(pool)
- .local_user(Some(&data.inserted_local_user))
- .build()
- .list()
- .await
- .unwrap();
+ let all_languages = CommentQuery {
+ local_user: (Some(&data.local_user_view)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
assert_eq!(5, all_languages.len());
// change user lang to finnish, should only show one post in finnish and one undetermined
.await
.unwrap()
.unwrap();
- LocalUserLanguage::update(pool, vec![finnish_id], data.inserted_local_user.id)
- .await
- .unwrap();
- let finnish_comments = CommentQuery::builder()
- .pool(pool)
- .local_user(Some(&data.inserted_local_user))
- .build()
- .list()
+ LocalUserLanguage::update(pool, vec![finnish_id], data.local_user_view.local_user.id)
.await
.unwrap();
+ let finnish_comments = CommentQuery {
+ local_user: (Some(&data.local_user_view)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
assert_eq!(2, finnish_comments.len());
let finnish_comment = finnish_comments
.iter()
);
// now show all comments with undetermined language (which is the default value)
- LocalUserLanguage::update(pool, vec![UNDETERMINED_ID], data.inserted_local_user.id)
- .await
- .unwrap();
- let undetermined_comment = CommentQuery::builder()
- .pool(pool)
- .local_user(Some(&data.inserted_local_user))
- .build()
- .list()
- .await
- .unwrap();
+ LocalUserLanguage::update(
+ pool,
+ vec![UNDETERMINED_ID],
+ data.local_user_view.local_user.id,
+ )
+ .await
+ .unwrap();
+ let undetermined_comment = CommentQuery {
+ local_user: (Some(&data.local_user_view)),
+ ..Default::default()
+ }
+ .list(pool)
+ .await
+ .unwrap();
assert_eq!(1, undetermined_comment.len());
cleanup(data, pool).await;
}
async fn cleanup(data: Data, pool: &mut DbPool<'_>) {
- CommentLike::remove(pool, data.inserted_person.id, data.inserted_comment_0.id)
- .await
- .unwrap();
+ CommentLike::remove(
+ pool,
+ data.local_user_view.person.id,
+ data.inserted_comment_0.id,
+ )
+ .await
+ .unwrap();
Comment::delete(pool, data.inserted_comment_0.id)
.await
.unwrap();
Community::delete(pool, data.inserted_community.id)
.await
.unwrap();
- Person::delete(pool, data.inserted_person.id).await.unwrap();
+ Person::delete(pool, data.local_user_view.person.id)
+ .await
+ .unwrap();
Person::delete(pool, data.inserted_person_2.id)
.await
.unwrap();
comment: Comment {
id: data.inserted_comment_0.id,
content: "Comment 0".into(),
- creator_id: data.inserted_person.id,
+ creator_id: data.local_user_view.person.id,
post_id: data.inserted_post.id,
removed: false,
deleted: false,
language_id: LanguageId(37),
},
creator: Person {
- id: data.inserted_person.id,
+ id: data.local_user_view.person.id,
name: "timmy".into(),
display_name: None,
- published: data.inserted_person.published,
+ published: data.local_user_view.person.published,
avatar: None,
- actor_id: data.inserted_person.actor_id.clone(),
+ actor_id: data.local_user_view.person.actor_id.clone(),
local: true,
banned: false,
deleted: false,
bio: None,
banner: None,
updated: None,
- inbox_url: data.inserted_person.inbox_url.clone(),
+ inbox_url: data.local_user_view.person.inbox_url.clone(),
shared_inbox_url: None,
matrix_user_id: None,
ban_expires: None,
instance_id: data.inserted_instance.id,
- private_key: data.inserted_person.private_key.clone(),
- public_key: data.inserted_person.public_key.clone(),
- last_refreshed_at: data.inserted_person.last_refreshed_at,
+ private_key: data.local_user_view.person.private_key.clone(),
+ public_key: data.local_user_view.person.public_key.clone(),
+ last_refreshed_at: data.local_user_view.person.last_refreshed_at,
},
post: Post {
id: data.inserted_post.id,
name: data.inserted_post.name.clone(),
- creator_id: data.inserted_person.id,
+ creator_id: data.local_user_view.person.id,
url: None,
body: None,
published: data.inserted_post.published,