]> Untitled Git - lemmy.git/blobdiff - crates/db_views/src/post_view.rs
Fixing hot_ranks and scores to append a published sort. (#3618)
[lemmy.git] / crates / db_views / src / post_view.rs
index 48faeca2850085a6d99893ba7df224a8cc185826..1d85df3c83e0ea6cd51817d7f378556fd528915c 100644 (file)
@@ -1,4 +1,4 @@
-use crate::structs::PostView;
+use crate::structs::{LocalUserView, PostView};
 use diesel::{
   debug_query,
   dsl::{now, IntervalDsl},
@@ -34,7 +34,6 @@ use lemmy_db_schema::{
   },
   source::{
     community::{Community, CommunityFollower, CommunityPersonBan},
-    local_user::LocalUser,
     person::Person,
     person_block::PersonBlock,
     post::{Post, PostRead, PostSaved},
@@ -146,13 +145,21 @@ impl PostView {
       .into_boxed();
 
     // Hide deleted and removed for non-admins or mods
-    // Note: one special use case for this flag variable is when end-user-delete post or mod-removed post.
     if !is_mod_or_admin.unwrap_or(false) {
       query = query
         .filter(community::removed.eq(false))
-        .filter(community::deleted.eq(false))
         .filter(post::removed.eq(false))
-        .filter(post::deleted.eq(false));
+        // users can see their own deleted posts
+        .filter(
+          community::deleted
+            .eq(false)
+            .or(post::creator_id.eq(person_id_join)),
+        )
+        .filter(
+          post::deleted
+            .eq(false)
+            .or(post::creator_id.eq(person_id_join)),
+        );
     }
 
     let (
@@ -199,12 +206,11 @@ pub struct PostQuery<'a> {
   pub sort: Option<SortType>,
   pub creator_id: Option<PersonId>,
   pub community_id: Option<CommunityId>,
-  pub local_user: Option<&'a LocalUser>,
+  pub local_user: Option<&'a LocalUserView>,
   pub search_term: Option<String>,
   pub url_search: Option<String>,
   pub saved_only: Option<bool>,
-  /// Used to show deleted or removed posts for admins
-  pub is_mod_or_admin: Option<bool>,
+  pub is_profile_view: Option<bool>,
   pub page: Option<i64>,
   pub limit: Option<i64>,
 }
@@ -214,8 +220,11 @@ impl<'a> PostQuery<'a> {
     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 = post::table
       .inner_join(person::table)
@@ -302,16 +311,23 @@ impl<'a> PostQuery<'a> {
       ))
       .into_boxed();
 
-    // Hide deleted and removed for non-admins or mods
-    // TODO This eventually needs to show posts where you are the creator
-    if !self.is_mod_or_admin.unwrap_or(false) {
+    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 posts to creator
+    if is_creator {
       query = query
-        .filter(community::removed.eq(false))
         .filter(community::deleted.eq(false))
-        .filter(post::removed.eq(false))
         .filter(post::deleted.eq(false));
     }
 
+    let is_admin = self.local_user.map(|l| l.person.admin).unwrap_or(false);
+    // only show removed posts to admin when viewing user profile
+    if !(is_profile_view && is_admin) {
+      query = query
+        .filter(community::removed.eq(false))
+        .filter(post::removed.eq(false));
+    }
+
     if self.community_id.is_none() {
       query = query.then_order_by(post_aggregates::featured_local.desc());
     } else if let Some(community_id) = self.community_id {
@@ -359,13 +375,21 @@ impl<'a> PostQuery<'a> {
       );
     }
 
-    if !self.local_user.map(|l| l.show_nsfw).unwrap_or(false) {
+    if !self
+      .local_user
+      .map(|l| l.local_user.show_nsfw)
+      .unwrap_or(false)
+    {
       query = query
         .filter(post::nsfw.eq(false))
         .filter(community::nsfw.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));
     };
 
@@ -374,7 +398,11 @@ impl<'a> PostQuery<'a> {
     }
     // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read
     // setting wont be able to see saved posts.
-    else if !self.local_user.map(|l| l.show_read_posts).unwrap_or(true) {
+    else if !self
+      .local_user
+      .map(|l| l.local_user.show_read_posts)
+      .unwrap_or(true)
+    {
       query = query.filter(post_read::post_id.is_null());
     }
 
@@ -388,8 +416,12 @@ impl<'a> PostQuery<'a> {
     }
 
     query = match self.sort.unwrap_or(SortType::Hot) {
-      SortType::Active => query.then_order_by(post_aggregates::hot_rank_active.desc()),
-      SortType::Hot => query.then_order_by(post_aggregates::hot_rank.desc()),
+      SortType::Active => query
+        .then_order_by(post_aggregates::hot_rank_active.desc())
+        .then_order_by(post_aggregates::published.desc()),
+      SortType::Hot => query
+        .then_order_by(post_aggregates::hot_rank.desc())
+        .then_order_by(post_aggregates::published.desc()),
       SortType::New => query.then_order_by(post_aggregates::published.desc()),
       SortType::Old => query.then_order_by(post_aggregates::published.asc()),
       SortType::NewComments => query.then_order_by(post_aggregates::newest_comment_time.desc()),
@@ -477,7 +509,10 @@ mod tests {
   #![allow(clippy::unwrap_used)]
   #![allow(clippy::indexing_slicing)]
 
-  use crate::post_view::{PostQuery, PostView};
+  use crate::{
+    post_view::{PostQuery, PostView},
+    structs::LocalUserView,
+  };
   use lemmy_db_schema::{
     aggregates::structs::PostAggregates,
     impls::actor_language::UNDETERMINED_ID,
@@ -502,8 +537,7 @@ mod tests {
 
   struct Data {
     inserted_instance: Instance,
-    inserted_person: Person,
-    inserted_local_user: LocalUser,
+    local_user_view: LocalUserView,
     inserted_blocked_person: Person,
     inserted_bot: Person,
     inserted_community: Community,
@@ -592,11 +626,15 @@ mod tests {
       .build();
 
     let _inserted_bot_post = Post::create(pool, &new_bot_post).await.unwrap();
+    let local_user_view = LocalUserView {
+      local_user: inserted_local_user,
+      person: inserted_person,
+      counts: Default::default(),
+    };
 
     Data {
       inserted_instance,
-      inserted_person,
-      inserted_local_user,
+      local_user_view,
       inserted_blocked_person,
       inserted_bot,
       inserted_community,
@@ -609,20 +647,21 @@ mod tests {
   async fn post_listing_with_person() {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
-    let data = init_data(pool).await;
+    let mut data = init_data(pool).await;
 
     let local_user_form = LocalUserUpdateForm::builder()
       .show_bot_accounts(Some(false))
       .build();
     let inserted_local_user =
-      LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
+      LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form)
         .await
         .unwrap();
+    data.local_user_view.local_user = inserted_local_user;
 
     let read_post_listing = PostQuery {
       sort: (Some(SortType::New)),
       community_id: (Some(data.inserted_community.id)),
-      local_user: (Some(&inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -632,7 +671,7 @@ mod tests {
     let post_listing_single_with_person = PostView::read(
       pool,
       data.inserted_post.id,
-      Some(data.inserted_person.id),
+      Some(data.local_user_view.person.id),
       None,
     )
     .await
@@ -654,14 +693,15 @@ mod tests {
       .show_bot_accounts(Some(true))
       .build();
     let inserted_local_user =
-      LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
+      LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form)
         .await
         .unwrap();
+    data.local_user_view.local_user = inserted_local_user;
 
     let post_listings_with_bots = PostQuery {
       sort: (Some(SortType::New)),
       community_id: (Some(data.inserted_community.id)),
-      local_user: (Some(&inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -719,7 +759,7 @@ mod tests {
     let data = init_data(pool).await;
 
     let community_block = CommunityBlockForm {
-      person_id: data.inserted_person.id,
+      person_id: data.local_user_view.person.id,
       community_id: data.inserted_community.id,
     };
     CommunityBlock::block(pool, &community_block).await.unwrap();
@@ -727,7 +767,7 @@ mod tests {
     let read_post_listings_with_person_after_block = PostQuery {
       sort: (Some(SortType::New)),
       community_id: (Some(data.inserted_community.id)),
-      local_user: (Some(&data.inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -747,11 +787,11 @@ mod tests {
   async fn post_listing_like() {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
-    let data = init_data(pool).await;
+    let mut data = init_data(pool).await;
 
     let post_like_form = PostLikeForm {
       post_id: data.inserted_post.id,
-      person_id: data.inserted_person.id,
+      person_id: data.local_user_view.person.id,
       score: 1,
     };
 
@@ -760,7 +800,7 @@ mod tests {
     let expected_post_like = PostLike {
       id: inserted_post_like.id,
       post_id: data.inserted_post.id,
-      person_id: data.inserted_person.id,
+      person_id: data.local_user_view.person.id,
       published: inserted_post_like.published,
       score: 1,
     };
@@ -769,7 +809,7 @@ mod tests {
     let post_listing_single_with_person = PostView::read(
       pool,
       data.inserted_post.id,
-      Some(data.inserted_person.id),
+      Some(data.local_user_view.person.id),
       None,
     )
     .await
@@ -785,14 +825,15 @@ mod tests {
       .show_bot_accounts(Some(false))
       .build();
     let inserted_local_user =
-      LocalUser::update(pool, data.inserted_local_user.id, &local_user_form)
+      LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form)
         .await
         .unwrap();
+    data.local_user_view.local_user = inserted_local_user;
 
     let read_post_listing = PostQuery {
       sort: (Some(SortType::New)),
       community_id: (Some(data.inserted_community.id)),
-      local_user: (Some(&inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -802,9 +843,10 @@ mod tests {
 
     assert_eq!(expected_post_with_upvote, read_post_listing[0]);
 
-    let like_removed = PostLike::remove(pool, data.inserted_person.id, data.inserted_post.id)
-      .await
-      .unwrap();
+    let like_removed =
+      PostLike::remove(pool, data.local_user_view.person.id, data.inserted_post.id)
+        .await
+        .unwrap();
     assert_eq!(1, like_removed);
     cleanup(data, pool).await;
   }
@@ -822,7 +864,7 @@ mod tests {
       .unwrap();
     let post_spanish = PostInsertForm::builder()
       .name("asffgdsc".to_string())
-      .creator_id(data.inserted_person.id)
+      .creator_id(data.local_user_view.person.id)
       .community_id(data.inserted_community.id)
       .language_id(Some(spanish_id))
       .build();
@@ -831,7 +873,7 @@ mod tests {
 
     let post_listings_all = PostQuery {
       sort: (Some(SortType::New)),
-      local_user: (Some(&data.inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -845,13 +887,13 @@ mod tests {
       .await
       .unwrap()
       .unwrap();
-    LocalUserLanguage::update(pool, vec![french_id], data.inserted_local_user.id)
+    LocalUserLanguage::update(pool, vec![french_id], data.local_user_view.local_user.id)
       .await
       .unwrap();
 
     let post_listing_french = PostQuery {
       sort: (Some(SortType::New)),
-      local_user: (Some(&data.inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -867,13 +909,13 @@ mod tests {
     LocalUserLanguage::update(
       pool,
       vec![french_id, UNDETERMINED_ID],
-      data.inserted_local_user.id,
+      data.local_user_view.local_user.id,
     )
     .await
     .unwrap();
     let post_listings_french_und = PostQuery {
       sort: (Some(SortType::New)),
-      local_user: (Some(&data.inserted_local_user)),
+      local_user: (Some(&data.local_user_view)),
       ..Default::default()
     }
     .list(pool)
@@ -893,55 +935,103 @@ mod tests {
 
   #[tokio::test]
   #[serial]
-  async fn post_listings_deleted() {
+  async fn post_listings_removed() {
     let pool = &build_db_pool_for_tests().await;
     let pool = &mut pool.into();
-    let data = init_data(pool).await;
+    let mut data = init_data(pool).await;
 
-    // Delete the post
+    // Remove the post
     Post::update(
       pool,
       data.inserted_post.id,
-      &PostUpdateForm::builder().deleted(Some(true)).build(),
+      &PostUpdateForm::builder().removed(Some(true)).build(),
     )
     .await
     .unwrap();
 
-    // Make sure you don't see the deleted post in the results
+    // Make sure you don't see the removed post in the results
     let post_listings_no_admin = PostQuery {
-      sort: (Some(SortType::New)),
-      local_user: (Some(&data.inserted_local_user)),
-      is_mod_or_admin: (Some(false)),
+      sort: Some(SortType::New),
+      local_user: Some(&data.local_user_view),
       ..Default::default()
     }
     .list(pool)
     .await
     .unwrap();
-
     assert_eq!(1, post_listings_no_admin.len());
 
-    // Make sure they see both
+    // Removed post is shown to admins on profile page
+    data.local_user_view.person.admin = true;
     let post_listings_is_admin = PostQuery {
-      sort: (Some(SortType::New)),
-      local_user: (Some(&data.inserted_local_user)),
-      is_mod_or_admin: (Some(true)),
+      sort: Some(SortType::New),
+      local_user: Some(&data.local_user_view),
+      is_profile_view: Some(true),
       ..Default::default()
     }
     .list(pool)
     .await
     .unwrap();
-
     assert_eq!(2, post_listings_is_admin.len());
 
     cleanup(data, pool).await;
   }
 
+  #[tokio::test]
+  #[serial]
+  async fn post_listings_deleted() {
+    let pool = &build_db_pool_for_tests().await;
+    let pool = &mut pool.into();
+    let data = init_data(pool).await;
+
+    // Delete the post
+    Post::update(
+      pool,
+      data.inserted_post.id,
+      &PostUpdateForm::builder().deleted(Some(true)).build(),
+    )
+    .await
+    .unwrap();
+
+    // Make sure you don't see the deleted post in the results
+    let post_listings_no_creator = PostQuery {
+      sort: Some(SortType::New),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+    let not_contains_deleted = post_listings_no_creator
+      .iter()
+      .map(|p| p.post.id)
+      .all(|p| p != data.inserted_post.id);
+    assert!(not_contains_deleted);
+
+    // Deleted post is shown to creator
+    let post_listings_is_creator = PostQuery {
+      sort: Some(SortType::New),
+      local_user: Some(&data.local_user_view),
+      ..Default::default()
+    }
+    .list(pool)
+    .await
+    .unwrap();
+    let contains_deleted = post_listings_is_creator
+      .iter()
+      .map(|p| p.post.id)
+      .any(|p| p == data.inserted_post.id);
+    assert!(contains_deleted);
+
+    cleanup(data, pool).await;
+  }
+
   async fn cleanup(data: Data, pool: &mut DbPool<'_>) {
     let num_deleted = Post::delete(pool, data.inserted_post.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_bot.id).await.unwrap();
     Person::delete(pool, data.inserted_blocked_person.id)
       .await
@@ -954,7 +1044,7 @@ mod tests {
 
   async fn expected_post_view(data: &Data, pool: &mut DbPool<'_>) -> PostView {
     let (inserted_person, inserted_community, inserted_post) = (
-      &data.inserted_person,
+      &data.local_user_view.person,
       &data.inserted_community,
       &data.inserted_post,
     );