]> Untitled Git - lemmy.git/commitdiff
Some API cleanup, adding site_id to site aggregates.
authorDessalines <tyhou13@gmx.com>
Sun, 20 Dec 2020 01:10:47 +0000 (20:10 -0500)
committerDessalines <tyhou13@gmx.com>
Sun, 20 Dec 2020 01:10:47 +0000 (20:10 -0500)
25 files changed:
lemmy_api/src/comment.rs
lemmy_api/src/community.rs
lemmy_api/src/lib.rs
lemmy_api/src/post.rs
lemmy_api/src/site.rs
lemmy_api/src/user.rs
lemmy_apub/src/activities/receive/comment.rs
lemmy_apub/src/activities/receive/private_message.rs
lemmy_apub/src/fetcher.rs
lemmy_apub/src/http/post.rs
lemmy_db/src/aggregates/site_aggregates.rs
lemmy_db/src/schema.rs
lemmy_db/src/source/post.rs
lemmy_db/src/source/site.rs
lemmy_db/src/views/comment_view.rs
lemmy_db/src/views/site_view.rs
lemmy_structs/src/comment.rs
lemmy_structs/src/community.rs
lemmy_structs/src/lib.rs
lemmy_structs/src/post.rs
lemmy_structs/src/site.rs
lemmy_structs/src/user.rs
lemmy_structs/src/websocket.rs [deleted file]
migrations/2020-12-02-152437_create_site_aggregates/down.sql
migrations/2020-12-02-152437_create_site_aggregates/up.sql

index 689fe4b8abb0da3e47c801344046db7e23c80dad..e5f079ad2ae395aa556d41315ac5eedc2117e2dc 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{
   check_community_ban,
+  check_downvotes_enabled,
   collect_moderated_communities,
   get_post,
   get_user_from_jwt,
@@ -11,16 +12,13 @@ use actix_web::web::Data;
 use lemmy_apub::{ApubLikeableType, ApubObjectType};
 use lemmy_db::{
   source::{
-    comment::*,
+    comment::{Comment, CommentForm, CommentLike, CommentLikeForm, CommentSaved, CommentSavedForm},
     comment_report::{CommentReport, CommentReportForm},
-    moderator::*,
-    post::*,
-    user::*,
+    moderator::{ModRemoveComment, ModRemoveCommentForm},
   },
   views::{
     comment_report_view::{CommentReportQueryBuilder, CommentReportView},
     comment_view::{CommentQueryBuilder, CommentView},
-    site_view::SiteView,
   },
   Crud,
   Likeable,
@@ -110,6 +108,7 @@ impl Perform for CreateComment {
     updated_comment.send_create(&user, context).await?;
 
     // Scan the comment for user mentions, add those rows
+    let post_id = post.id;
     let mentions = scrape_text_for_mentions(&comment_form.content);
     let recipient_ids = send_local_notifs(
       mentions,
@@ -124,7 +123,7 @@ impl Perform for CreateComment {
     // You like your own comment by default
     let like_form = CommentLikeForm {
       comment_id: inserted_comment.id,
-      post_id: data.post_id,
+      post_id,
       user_id: user.id,
       score: 1,
     };
@@ -156,6 +155,7 @@ impl Perform for CreateComment {
 
     // strip out the recipient_ids, so that
     // users don't get double notifs
+    // TODO Do this in a different way
     res.recipient_ids = Vec::new();
 
     Ok(res)
@@ -203,16 +203,13 @@ impl Perform for EditComment {
     updated_comment.send_update(&user, context).await?;
 
     // Do the mentions / recipients
-    let post_id = orig_comment.post.id;
-    let post = get_post(post_id, context.pool()).await?;
-
     let updated_comment_content = updated_comment.content.to_owned();
     let mentions = scrape_text_for_mentions(&updated_comment_content);
     let recipient_ids = send_local_notifs(
       mentions,
       updated_comment,
       &user,
-      post,
+      orig_comment.post,
       context.pool(),
       false,
     )
@@ -239,6 +236,7 @@ impl Perform for EditComment {
 
     // strip out the recipient_ids, so that
     // users don't get double notifs
+    // TODO again
     res.recipient_ids = Vec::new();
 
     Ok(res)
@@ -297,14 +295,13 @@ impl Perform for DeleteComment {
     .await??;
 
     // Build the recipients
-    let post_id = comment_view.post.id;
-    let post = get_post(post_id, context.pool()).await?;
+    let comment_view_2 = comment_view.clone();
     let mentions = vec![];
     let recipient_ids = send_local_notifs(
       mentions,
       updated_comment,
       &user,
-      post,
+      comment_view_2.post,
       context.pool(),
       false,
     )
@@ -313,7 +310,7 @@ impl Perform for DeleteComment {
     let mut res = CommentResponse {
       comment_view,
       recipient_ids,
-      form_id: None,
+      form_id: None, // TODO a comment delete might clear forms?
     };
 
     context.chat_server().do_send(SendComment {
@@ -324,6 +321,7 @@ impl Perform for DeleteComment {
 
     // strip out the recipient_ids, so that
     // users don't get double notifs
+    // TODO again
     res.recipient_ids = Vec::new();
 
     Ok(res)
@@ -392,14 +390,14 @@ impl Perform for RemoveComment {
     .await??;
 
     // Build the recipients
-    let post_id = comment_view.post.id;
-    let post = get_post(post_id, context.pool()).await?;
+    let comment_view_2 = comment_view.clone();
+
     let mentions = vec![];
     let recipient_ids = send_local_notifs(
       mentions,
       updated_comment,
       &user,
-      post,
+      comment_view_2.post,
       context.pool(),
       false,
     )
@@ -408,7 +406,7 @@ impl Perform for RemoveComment {
     let mut res = CommentResponse {
       comment_view,
       recipient_ids,
-      form_id: None,
+      form_id: None, // TODO maybe this might clear other forms
     };
 
     context.chat_server().do_send(SendComment {
@@ -419,6 +417,7 @@ impl Perform for RemoveComment {
 
     // strip out the recipient_ids, so that
     // users don't get double notifs
+    // TODO again
     res.recipient_ids = Vec::new();
 
     Ok(res)
@@ -437,41 +436,23 @@ impl Perform for MarkCommentAsRead {
     let data: &MarkCommentAsRead = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
 
-    let edit_id = data.edit_id;
+    let comment_id = data.comment_id;
     let orig_comment = blocking(context.pool(), move |conn| {
-      CommentView::read(&conn, edit_id, None)
+      CommentView::read(&conn, comment_id, None)
     })
     .await??;
 
     check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
 
     // Verify that only the recipient can mark as read
-    // Needs to fetch the parent comment / post to get the recipient
-    let parent_id = orig_comment.comment.parent_id;
-    match parent_id {
-      Some(pid) => {
-        let parent_comment = blocking(context.pool(), move |conn| {
-          CommentView::read(&conn, pid, None)
-        })
-        .await??;
-        if user.id != parent_comment.creator.id {
-          return Err(APIError::err("no_comment_edit_allowed").into());
-        }
-      }
-      None => {
-        let parent_post_id = orig_comment.post.id;
-        let parent_post =
-          blocking(context.pool(), move |conn| Post::read(conn, parent_post_id)).await??;
-        if user.id != parent_post.creator_id {
-          return Err(APIError::err("no_comment_edit_allowed").into());
-        }
-      }
+    if user.id != orig_comment.get_recipient_id() {
+      return Err(APIError::err("no_comment_edit_allowed").into());
     }
 
     // Do the mark as read
     let read = data.read;
     match blocking(context.pool(), move |conn| {
-      Comment::update_read(conn, edit_id, read)
+      Comment::update_read(conn, comment_id, read)
     })
     .await?
     {
@@ -480,7 +461,7 @@ impl Perform for MarkCommentAsRead {
     };
 
     // Refetch it
-    let edit_id = data.edit_id;
+    let edit_id = data.comment_id;
     let user_id = user.id;
     let comment_view = blocking(context.pool(), move |conn| {
       CommentView::read(conn, edit_id, Some(user_id))
@@ -556,12 +537,7 @@ impl Perform for CreateCommentLike {
     let mut recipient_ids = Vec::new();
 
     // Don't do a downvote if site has downvotes disabled
-    if data.score == -1 {
-      let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
-      if !site_view.site.enable_downvotes {
-        return Err(APIError::err("downvotes_disabled").into());
-      }
-    }
+    check_downvotes_enabled(data.score, context.pool()).await?;
 
     let comment_id = data.comment_id;
     let orig_comment = blocking(context.pool(), move |conn| {
@@ -569,34 +545,14 @@ impl Perform for CreateCommentLike {
     })
     .await??;
 
-    let post_id = orig_comment.post.id;
-    let post = get_post(post_id, context.pool()).await?;
-    check_community_ban(user.id, post.community_id, context.pool()).await?;
+    check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
 
-    let comment_id = data.comment_id;
-    let comment = blocking(context.pool(), move |conn| Comment::read(conn, comment_id)).await??;
-
-    // Add to recipient ids
-    match comment.parent_id {
-      Some(parent_id) => {
-        let parent_comment =
-          blocking(context.pool(), move |conn| Comment::read(conn, parent_id)).await??;
-        if parent_comment.creator_id != user.id {
-          let parent_user = blocking(context.pool(), move |conn| {
-            User_::read(conn, parent_comment.creator_id)
-          })
-          .await??;
-          recipient_ids.push(parent_user.id);
-        }
-      }
-      None => {
-        recipient_ids.push(post.creator_id);
-      }
-    }
+    // Add parent user to recipients
+    recipient_ids.push(orig_comment.get_recipient_id());
 
     let like_form = CommentLikeForm {
       comment_id: data.comment_id,
-      post_id,
+      post_id: orig_comment.post.id,
       user_id: user.id,
       score: data.score,
     };
@@ -609,6 +565,7 @@ impl Perform for CreateCommentLike {
     .await??;
 
     // Only add the like if the score isnt 0
+    let comment = orig_comment.comment;
     let do_add = like_form.score != 0 && (like_form.score == 1 || like_form.score == -1);
     if do_add {
       let like_form2 = like_form.clone();
@@ -649,6 +606,7 @@ impl Perform for CreateCommentLike {
     // strip out the recipient_ids, so that
     // users don't get double notifs
     res.recipient_ids = Vec::new();
+    // TODO why
 
     Ok(res)
   }
index 6e20a30ba3ef8bda2092119b3e42f1e7b6196cf6..c5ac408295f47a251e34cb17755f6292922868cc 100644 (file)
@@ -58,20 +58,22 @@ impl Perform for GetCommunity {
     let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
     let user_id = user.map(|u| u.id);
 
-    let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
-    let community = match data.id {
-      Some(id) => blocking(context.pool(), move |conn| Community::read(conn, id)).await??,
-      None => match blocking(context.pool(), move |conn| {
-        Community::read_from_name(conn, &name)
-      })
-      .await?
-      {
-        Ok(community) => community,
-        Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
-      },
+    let community_id = match data.id {
+      Some(id) => id,
+      None => {
+        let name = data.name.to_owned().unwrap_or_else(|| "main".to_string());
+        match blocking(context.pool(), move |conn| {
+          Community::read_from_name(conn, &name)
+        })
+        .await?
+        {
+          Ok(community) => community,
+          Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
+        }
+        .id
+      }
     };
 
-    let community_id = community.id;
     let community_view = match blocking(context.pool(), move |conn| {
       CommunityView::read(conn, community_id, user_id)
     })
@@ -81,7 +83,6 @@ impl Perform for GetCommunity {
       Err(_e) => return Err(APIError::err("couldnt_find_community").into()),
     };
 
-    let community_id = community.id;
     let moderators: Vec<CommunityModeratorView> = match blocking(context.pool(), move |conn| {
       CommunityModeratorView::for_community(conn, community_id)
     })
@@ -178,6 +179,7 @@ impl Perform for CreateCommunity {
       Err(_e) => return Err(APIError::err("community_already_exists").into()),
     };
 
+    // The community creator becomes a moderator
     let community_moderator_form = CommunityModeratorForm {
       community_id: inserted_community.id,
       user_id: user.id,
@@ -188,6 +190,7 @@ impl Perform for CreateCommunity {
       return Err(APIError::err("community_moderator_already_exists").into());
     }
 
+    // Follow your own community
     let community_follower_form = CommunityFollowerForm {
       community_id: inserted_community.id,
       user_id: user.id,
@@ -584,15 +587,15 @@ impl Perform for BanFromCommunity {
     }
 
     // Remove/Restore their data if that's desired
-    if let Some(remove_data) = data.remove_data {
+    if data.remove_data {
       // Posts
       blocking(context.pool(), move |conn: &'_ _| {
-        Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), remove_data)
+        Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), true)
       })
       .await??;
 
       // Comments
-      // Diesel doesn't allow updates with joins, so this has to be a loop
+      // TODO Diesel doesn't allow updates with joins, so this has to be a loop
       let comments = blocking(context.pool(), move |conn| {
         CommentQueryBuilder::create(conn)
           .creator_id(banned_user_id)
@@ -605,7 +608,7 @@ impl Perform for BanFromCommunity {
       for comment_view in &comments {
         let comment_id = comment_view.comment.id;
         blocking(context.pool(), move |conn: &'_ _| {
-          Comment::update_removed(conn, comment_id, remove_data)
+          Comment::update_removed(conn, comment_id, true)
         })
         .await??;
       }
@@ -743,6 +746,7 @@ impl Perform for TransferCommunity {
 
     let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
 
+    // Making sure the creator, if an admin, is at the top
     let creator_index = admins
       .iter()
       .position(|r| r.user.id == site_creator_id)
index ad7355e1cb59326ecbcdd59c0529a68137cedbcc..eadb0d1ac9278e8e58318b09662173d61510daba 100644 (file)
@@ -4,6 +4,7 @@ use lemmy_db::{
   source::{
     community::{Community, CommunityModerator},
     post::Post,
+    site::Site,
     user::User_,
   },
   views::community::community_user_ban_view::CommunityUserBanView,
@@ -102,6 +103,16 @@ pub(crate) async fn check_community_ban(
   }
 }
 
+pub(crate) async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result<(), LemmyError> {
+  if score == -1 {
+    let site = blocking(pool, move |conn| Site::read_simple(conn)).await??;
+    if !site.enable_downvotes {
+      return Err(APIError::err("downvotes_disabled").into());
+    }
+  }
+  Ok(())
+}
+
 /// Returns a list of communities that the user moderates
 /// or if a community_id is supplied validates the user is a moderator
 /// of that community and returns the community id in a vec
index 22f95877a294ae5e4e7bc1cdf3c25f267ea411cd..f021b0d7ce2bc4545e423f11b392fcaf6fc34ff2 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{
   check_community_ban,
+  check_downvotes_enabled,
   check_optional_url,
   collect_moderated_communities,
   get_user_from_jwt,
@@ -18,10 +19,9 @@ use lemmy_db::{
   },
   views::{
     comment_view::CommentQueryBuilder,
-    community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
+    community::community_moderator_view::CommunityModeratorView,
     post_report_view::{PostReportQueryBuilder, PostReportView},
     post_view::{PostQueryBuilder, PostView},
-    site_view::SiteView,
   },
   Crud,
   Likeable,
@@ -192,12 +192,6 @@ impl Perform for GetPost {
     })
     .await??;
 
-    let community_id = post_view.community.id;
-    let community = blocking(context.pool(), move |conn| {
-      CommunityView::read(conn, community_id, user_id)
-    })
-    .await??;
-
     let community_id = post_view.community.id;
     let moderators = blocking(context.pool(), move |conn| {
       CommunityModeratorView::for_community(conn, community_id)
@@ -214,7 +208,6 @@ impl Perform for GetPost {
     Ok(GetPostResponse {
       post_view,
       comments,
-      community,
       moderators,
       online,
     })
@@ -285,12 +278,7 @@ impl Perform for CreatePostLike {
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
 
     // Don't do a downvote if site has downvotes disabled
-    if data.score == -1 {
-      let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
-      if !site_view.site.enable_downvotes {
-        return Err(APIError::err("downvotes_disabled").into());
-      }
-    }
+    check_downvotes_enabled(data.score, context.pool()).await?;
 
     // Check for a community ban
     let post_id = data.post_id;
index 138cc8751edaa4bbcc14d0f9e435c67504d1cdb3..16c6ecec9bd7063a440ac791be5148f695858669 100644 (file)
@@ -10,7 +10,6 @@ use actix_web::web::Data;
 use anyhow::Context;
 use lemmy_apub::fetcher::search_by_apub_id;
 use lemmy_db::{
-  aggregates::site_aggregates::SiteAggregates,
   diesel_option_overwrite,
   naive_now,
   source::{category::*, moderator::*, site::*},
@@ -156,7 +155,7 @@ impl Perform for CreateSite {
   ) -> Result<SiteResponse, LemmyError> {
     let data: &CreateSite = &self;
 
-    let read_site = move |conn: &'_ _| Site::read(conn, 1);
+    let read_site = move |conn: &'_ _| Site::read_simple(conn);
     if blocking(context.pool(), read_site).await?.is_ok() {
       return Err(APIError::err("site_already_exists").into());
     };
@@ -188,7 +187,7 @@ impl Perform for CreateSite {
 
     let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
 
-    Ok(SiteResponse { site: site_view })
+    Ok(SiteResponse { site_view })
   }
 }
 
@@ -209,7 +208,7 @@ impl Perform for EditSite {
     // Make sure user is an admin
     is_admin(context.pool(), user.id).await?;
 
-    let found_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??;
+    let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
 
     let icon = diesel_option_overwrite(&data.icon);
     let banner = diesel_option_overwrite(&data.banner);
@@ -233,7 +232,7 @@ impl Perform for EditSite {
 
     let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
 
-    let res = SiteResponse { site: site_view };
+    let res = SiteResponse { site_view };
 
     context.chat_server().do_send(SendAllMessage {
       op: UserOperation::EditSite,
@@ -256,39 +255,41 @@ impl Perform for GetSite {
   ) -> Result<GetSiteResponse, LemmyError> {
     let data: &GetSite = &self;
 
-    // TODO refactor this a little
-    let res = blocking(context.pool(), move |conn| Site::read(conn, 1)).await?;
-    let site_view = if res.is_ok() {
-      Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
-    } else if let Some(setup) = Settings::get().setup.as_ref() {
-      let register = Register {
-        username: setup.admin_username.to_owned(),
-        email: setup.admin_email.to_owned(),
-        password: setup.admin_password.to_owned(),
-        password_verify: setup.admin_password.to_owned(),
-        admin: true,
-        show_nsfw: true,
-        captcha_uuid: None,
-        captcha_answer: None,
-      };
-      let login_response = register.perform(context, websocket_id).await?;
-      info!("Admin {} created", setup.admin_username);
-
-      let create_site = CreateSite {
-        name: setup.site_name.to_owned(),
-        description: None,
-        icon: None,
-        banner: None,
-        enable_downvotes: true,
-        open_registration: true,
-        enable_nsfw: true,
-        auth: login_response.jwt,
-      };
-      create_site.perform(context, websocket_id).await?;
-      info!("Site {} created", setup.site_name);
-      Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
-    } else {
-      None
+    let site_view = match blocking(context.pool(), move |conn| SiteView::read(conn)).await? {
+      Ok(site_view) => Some(site_view),
+      // If the site isn't created yet, check the setup
+      Err(_) => {
+        if let Some(setup) = Settings::get().setup.as_ref() {
+          let register = Register {
+            username: setup.admin_username.to_owned(),
+            email: setup.admin_email.to_owned(),
+            password: setup.admin_password.to_owned(),
+            password_verify: setup.admin_password.to_owned(),
+            admin: true,
+            show_nsfw: true,
+            captcha_uuid: None,
+            captcha_answer: None,
+          };
+          let login_response = register.perform(context, websocket_id).await?;
+          info!("Admin {} created", setup.admin_username);
+
+          let create_site = CreateSite {
+            name: setup.site_name.to_owned(),
+            description: None,
+            icon: None,
+            banner: None,
+            enable_downvotes: true,
+            open_registration: true,
+            enable_nsfw: true,
+            auth: login_response.jwt,
+          };
+          create_site.perform(context, websocket_id).await?;
+          info!("Site {} created", setup.site_name);
+          Some(blocking(context.pool(), move |conn| SiteView::read(conn)).await??)
+        } else {
+          None
+        }
+      }
     };
 
     let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
@@ -321,17 +322,14 @@ impl Perform for GetSite {
         u
       });
 
-    let counts = blocking(context.pool(), move |conn| SiteAggregates::read(conn)).await??;
-
     Ok(GetSiteResponse {
-      site: site_view,
+      site_view,
       admins,
       banned,
       online,
       version: version::VERSION.to_string(),
       my_user,
       federated_instances: linked_instances(context.pool()).await?,
-      counts,
     })
   }
 }
@@ -521,7 +519,7 @@ impl Perform for TransferSite {
     user.private_key = None;
     user.public_key = None;
 
-    let read_site = blocking(context.pool(), move |conn| Site::read(conn, 1)).await??;
+    let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
 
     // Make sure user is the creator
     if read_site.creator_id != user.id {
@@ -555,17 +553,14 @@ impl Perform for TransferSite {
 
     let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
 
-    let counts = blocking(context.pool(), move |conn| SiteAggregates::read(conn)).await??;
-
     Ok(GetSiteResponse {
-      site: Some(site_view),
+      site_view: Some(site_view),
       admins,
       banned,
       online: 0,
       version: version::VERSION.to_string(),
       my_user: Some(user),
       federated_instances: linked_instances(context.pool()).await?,
-      counts,
     })
   }
 }
@@ -604,12 +599,8 @@ impl Perform for SaveSiteConfig {
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
 
     // Only let admins read this
-    let admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
-    let admin_ids: Vec<i32> = admins.into_iter().map(|m| m.user.id).collect();
-
-    if !admin_ids.contains(&user.id) {
-      return Err(APIError::err("not_an_admin").into());
-    }
+    let user_id = user.id;
+    is_admin(context.pool(), user_id).await?;
 
     // Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
     let config_hjson = match Settings::save_config_file(&data.config_hjson) {
index f31e42e5a9cf12b095b32092dfa055275e601448..cca8dffb8909225d06ecb23c12ce5f9fef75ea60 100644 (file)
@@ -38,7 +38,6 @@ use lemmy_db::{
     post_report_view::PostReportView,
     post_view::PostQueryBuilder,
     private_message_view::{PrivateMessageQueryBuilder, PrivateMessageView},
-    site_view::SiteView,
     user_mention_view::{UserMentionQueryBuilder, UserMentionView},
     user_view::{UserViewDangerous, UserViewSafe},
   },
@@ -120,8 +119,8 @@ impl Perform for Register {
     let data: &Register = &self;
 
     // Make sure site has open registration
-    if let Ok(site_view) = blocking(context.pool(), move |conn| SiteView::read(conn)).await? {
-      if !site_view.site.open_registration {
+    if let Ok(site) = blocking(context.pool(), move |conn| Site::read_simple(conn)).await? {
+      if !site.open_registration {
         return Err(APIError::err("registration_closed").into());
       }
     }
@@ -347,9 +346,6 @@ impl Perform for SaveUserSettings {
     let data: &SaveUserSettings = &self;
     let user = get_user_from_jwt(&data.auth, context.pool()).await?;
 
-    let user_id = user.id;
-    let read_user = blocking(context.pool(), move |conn| User_::read(conn, user_id)).await??;
-
     let avatar = diesel_option_overwrite(&data.avatar);
     let banner = diesel_option_overwrite(&data.banner);
     let email = diesel_option_overwrite(&data.email);
@@ -373,6 +369,7 @@ impl Perform for SaveUserSettings {
       }
     }
 
+    let user_id = user.id;
     let password_encrypted = match &data.new_password {
       Some(new_password) => {
         match &data.new_password_verify {
@@ -385,8 +382,7 @@ impl Perform for SaveUserSettings {
             // Check the old password
             match &data.old_password {
               Some(old_password) => {
-                let valid: bool =
-                  verify(old_password, &read_user.password_encrypted).unwrap_or(false);
+                let valid: bool = verify(old_password, &user.password_encrypted).unwrap_or(false);
                 if !valid {
                   return Err(APIError::err("password_incorrect").into());
                 }
@@ -403,33 +399,36 @@ impl Perform for SaveUserSettings {
           None => return Err(APIError::err("passwords_dont_match").into()),
         }
       }
-      None => read_user.password_encrypted,
+      None => user.password_encrypted,
     };
 
+    let default_listing_type = ListingType::from_str(&data.default_listing_type)? as i16;
+    let default_sort_type = SortType::from_str(&data.default_sort_type)? as i16;
+
     let user_form = UserForm {
-      name: read_user.name,
+      name: user.name,
       email,
       matrix_user_id,
       avatar,
       banner,
       password_encrypted,
       preferred_username,
-      published: Some(read_user.published),
+      published: Some(user.published),
       updated: Some(naive_now()),
-      admin: read_user.admin,
-      banned: Some(read_user.banned),
+      admin: user.admin,
+      banned: Some(user.banned),
       show_nsfw: data.show_nsfw,
       theme: data.theme.to_owned(),
-      default_sort_type: data.default_sort_type,
-      default_listing_type: data.default_listing_type,
+      default_sort_type,
+      default_listing_type,
       lang: data.lang.to_owned(),
       show_avatars: data.show_avatars,
       send_notifications_to_email: data.send_notifications_to_email,
-      actor_id: Some(read_user.actor_id),
+      actor_id: Some(user.actor_id),
       bio,
-      local: read_user.local,
-      private_key: read_user.private_key,
-      public_key: read_user.public_key,
+      local: user.local,
+      private_key: user.private_key,
+      public_key: user.public_key,
       last_refreshed_at: None,
     };
 
@@ -579,9 +578,8 @@ impl Perform for GetUserDetails {
 
     // Return the jwt
     Ok(GetUserDetailsResponse {
-      // TODO need to figure out dangerous user view here
-      user: user_view,
-      user_dangerous,
+      user_view,
+      user_view_dangerous: user_dangerous,
       follows,
       moderates,
       comments,
@@ -669,22 +667,22 @@ impl Perform for BanUser {
     }
 
     // Remove their data if that's desired
-    if let Some(remove_data) = data.remove_data {
+    if data.remove_data {
       // Posts
       blocking(context.pool(), move |conn: &'_ _| {
-        Post::update_removed_for_creator(conn, banned_user_id, None, remove_data)
+        Post::update_removed_for_creator(conn, banned_user_id, None, true)
       })
       .await??;
 
       // Communities
       blocking(context.pool(), move |conn: &'_ _| {
-        Community::update_removed_for_creator(conn, banned_user_id, remove_data)
+        Community::update_removed_for_creator(conn, banned_user_id, true)
       })
       .await??;
 
       // Comments
       blocking(context.pool(), move |conn: &'_ _| {
-        Comment::update_removed_for_creator(conn, banned_user_id, remove_data)
+        Comment::update_removed_for_creator(conn, banned_user_id, true)
       })
       .await??;
     }
@@ -712,7 +710,7 @@ impl Perform for BanUser {
     .await??;
 
     let res = BanUserResponse {
-      user: user_view,
+      user_view,
       banned: data.ban,
     };
 
@@ -1091,7 +1089,9 @@ impl Perform for CreatePrivateMessage {
     })
     .await??;
 
-    let res = PrivateMessageResponse { message };
+    let res = PrivateMessageResponse {
+      private_message_view: message,
+    };
 
     context.chat_server().do_send(SendUserRoomMessage {
       op: UserOperation::CreatePrivateMessage,
@@ -1148,7 +1148,9 @@ impl Perform for EditPrivateMessage {
     .await??;
     let recipient_id = message.recipient.id;
 
-    let res = PrivateMessageResponse { message };
+    let res = PrivateMessageResponse {
+      private_message_view: message,
+    };
 
     context.chat_server().do_send(SendUserRoomMessage {
       op: UserOperation::EditPrivateMessage,
@@ -1211,7 +1213,9 @@ impl Perform for DeletePrivateMessage {
     .await??;
     let recipient_id = message.recipient.id;
 
-    let res = PrivateMessageResponse { message };
+    let res = PrivateMessageResponse {
+      private_message_view: message,
+    };
 
     context.chat_server().do_send(SendUserRoomMessage {
       op: UserOperation::DeletePrivateMessage,
@@ -1267,7 +1271,9 @@ impl Perform for MarkPrivateMessageAsRead {
     .await??;
     let recipient_id = message.recipient.id;
 
-    let res = PrivateMessageResponse { message };
+    let res = PrivateMessageResponse {
+      private_message_view: message,
+    };
 
     context.chat_server().do_send(SendUserRoomMessage {
       op: UserOperation::MarkPrivateMessageAsRead,
@@ -1305,7 +1311,9 @@ impl Perform for GetPrivateMessages {
     })
     .await??;
 
-    Ok(PrivateMessagesResponse { messages })
+    Ok(PrivateMessagesResponse {
+      private_messages: messages,
+    })
   }
 }
 
index 700a2653c130a4f617e830d3b664b0c097d8fa01..32eb8c0ca5290b5028032e2ac1fdbe284b46820f 100644 (file)
@@ -10,6 +10,7 @@ use lemmy_db::{
     post::Post,
   },
   views::comment_view::CommentView,
+  Crud,
   Likeable,
 };
 use lemmy_structs::{blocking, comment::CommentResponse, send_local_notifs};
index 15cde53f275911b5b04eed445fbfcc6981335635..8f7952b6b067fa5bdf93a6039b75fe97217baad7 100644 (file)
@@ -47,9 +47,11 @@ pub(crate) async fn receive_create_private_message(
   })
   .await??;
 
-  let res = PrivateMessageResponse { message };
+  let res = PrivateMessageResponse {
+    private_message_view: message,
+  };
 
-  let recipient_id = res.message.recipient.id;
+  let recipient_id = res.private_message_view.recipient.id;
 
   context.chat_server().do_send(SendUserRoomMessage {
     op: UserOperation::CreatePrivateMessage,
@@ -85,9 +87,11 @@ pub(crate) async fn receive_update_private_message(
   })
   .await??;
 
-  let res = PrivateMessageResponse { message };
+  let res = PrivateMessageResponse {
+    private_message_view: message,
+  };
 
-  let recipient_id = res.message.recipient.id;
+  let recipient_id = res.private_message_view.recipient.id;
 
   context.chat_server().do_send(SendUserRoomMessage {
     op: UserOperation::EditPrivateMessage,
@@ -117,8 +121,10 @@ pub(crate) async fn receive_delete_private_message(
   })
   .await??;
 
-  let res = PrivateMessageResponse { message };
-  let recipient_id = res.message.recipient.id;
+  let res = PrivateMessageResponse {
+    private_message_view: message,
+  };
+  let recipient_id = res.private_message_view.recipient.id;
   context.chat_server().do_send(SendUserRoomMessage {
     op: UserOperation::EditPrivateMessage,
     response: res,
@@ -152,8 +158,10 @@ pub(crate) async fn receive_undo_delete_private_message(
   })
   .await??;
 
-  let res = PrivateMessageResponse { message };
-  let recipient_id = res.message.recipient.id;
+  let res = PrivateMessageResponse {
+    private_message_view: message,
+  };
+  let recipient_id = res.private_message_view.recipient.id;
   context.chat_server().do_send(SendUserRoomMessage {
     op: UserOperation::EditPrivateMessage,
     response: res,
index 61cdbd47ab4b63e5c8d696e1452a20b1fe38013f..39188f138e361d51360562accfe8694b6b3553e3 100644 (file)
@@ -27,6 +27,7 @@ use lemmy_db::{
     user_view::UserViewSafe,
   },
   ApubObject,
+  Crud,
   Joinable,
   SearchType,
 };
index 563af8456d9d4234739979aeb942a6cd2b983bb1..3d0c6ff8eb98a3c77e51c468c34b426732412ab7 100644 (file)
@@ -4,7 +4,7 @@ use crate::{
 };
 use actix_web::{body::Body, web, HttpResponse};
 use diesel::result::Error::NotFound;
-use lemmy_db::source::post::Post;
+use lemmy_db::{source::post::Post, Crud};
 use lemmy_structs::blocking;
 use lemmy_utils::LemmyError;
 use lemmy_websocket::LemmyContext;
index 6856bfc9e5a411cf8c69bdd3ac83983f9344b16f..794dd53180c413f118dcdcb94e5b2a212ada7b4d 100644 (file)
@@ -2,10 +2,11 @@ use crate::schema::site_aggregates;
 use diesel::{result::Error, *};
 use serde::Serialize;
 
-#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize)]
+#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
 #[table_name = "site_aggregates"]
 pub struct SiteAggregates {
   pub id: i32,
+  pub site_id: i32,
   pub users: i64,
   pub posts: i64,
   pub comments: i64,
index 33e2389fdb929be0ee7d4954d03fc7b45e8f8a34..f0aca2db90acb8c032cbd55a3b4c46dda6bd2b0d 100644 (file)
@@ -362,6 +362,7 @@ table! {
 table! {
     site_aggregates (id) {
         id -> Int4,
+        site_id -> Int4,
         users -> Int8,
         posts -> Int8,
         comments -> Int8,
@@ -560,6 +561,7 @@ joinable!(post_report -> post (post_id));
 joinable!(post_saved -> post (post_id));
 joinable!(post_saved -> user_ (user_id));
 joinable!(site -> user_ (creator_id));
+joinable!(site_aggregates -> site (site_id));
 joinable!(user_aggregates -> user_ (user_id));
 joinable!(user_ban -> user_ (user_id));
 joinable!(user_mention -> comment (comment_id));
index 098ce8835316db5a72a6c005773e3ce4a3581634..948791ea4ae1f8abfd75b40a06a8a0e30e5113d1 100644 (file)
@@ -106,11 +106,6 @@ impl ApubObject<PostForm> for Post {
 }
 
 impl Post {
-  pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
-    use crate::schema::post::dsl::*;
-    post.filter(id.eq(post_id)).first::<Self>(conn)
-  }
-
   pub fn list_for_community(
     conn: &PgConnection,
     the_community_id: i32,
index 2f3fbcdff15859930d23a1676b3397295fa5e65a..1224e0ab7a8fc61453f00da1590b2e514f0196f0 100644 (file)
@@ -59,4 +59,9 @@ impl Site {
       .set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
       .get_result::<Self>(conn)
   }
+
+  pub fn read_simple(conn: &PgConnection) -> Result<Self, Error> {
+    use crate::schema::site::dsl::*;
+    site.first::<Self>(conn)
+  }
 }
index 35a9038ded34991063fda8fa08f041825fb35d15..8c7584471914445333eeb4d09cdb4463889bbd5e 100644 (file)
@@ -145,6 +145,15 @@ impl CommentView {
       my_vote,
     })
   }
+
+  /// Gets the recipient user id.
+  /// If there is no parent comment, its the post creator
+  pub fn get_recipient_id(&self) -> i32 {
+    match &self.recipient {
+      Some(parent_commenter) => parent_commenter.id,
+      None => self.post.creator_id,
+    }
+  }
 }
 
 pub struct CommentQueryBuilder<'a> {
index d10702fca95bb07b17af0818f5ece8c70f3376f9..3c605277e10e646f16c35967da86771e26439e38 100644 (file)
@@ -1,5 +1,6 @@
 use crate::{
-  schema::{site, user_},
+  aggregates::site_aggregates::SiteAggregates,
+  schema::{site, site_aggregates, user_},
   source::{
     site::Site,
     user::{UserSafe, User_},
@@ -13,15 +14,25 @@ use serde::Serialize;
 pub struct SiteView {
   pub site: Site,
   pub creator: UserSafe,
+  pub counts: SiteAggregates,
 }
 
 impl SiteView {
   pub fn read(conn: &PgConnection) -> Result<Self, Error> {
-    let (site, creator) = site::table
+    let (site, creator, counts) = site::table
       .inner_join(user_::table)
-      .select((site::all_columns, User_::safe_columns_tuple()))
-      .first::<(Site, UserSafe)>(conn)?;
+      .inner_join(site_aggregates::table)
+      .select((
+        site::all_columns,
+        User_::safe_columns_tuple(),
+        site_aggregates::all_columns,
+      ))
+      .first::<(Site, UserSafe, SiteAggregates)>(conn)?;
 
-    Ok(SiteView { site, creator })
+    Ok(SiteView {
+      site,
+      creator,
+      counts,
+    })
   }
 }
index be10906aa0e28854d6fa42ae15068656ff82c74b..fe65738d873d801d2f71b020f29994856e05ed7f 100644 (file)
@@ -35,7 +35,7 @@ pub struct RemoveComment {
 
 #[derive(Deserialize)]
 pub struct MarkCommentAsRead {
-  pub edit_id: i32,
+  pub comment_id: i32,
   pub read: bool,
   pub auth: String,
 }
@@ -50,8 +50,8 @@ pub struct SaveComment {
 #[derive(Serialize, Clone)]
 pub struct CommentResponse {
   pub comment_view: CommentView,
-  pub recipient_ids: Vec<i32>,
-  pub form_id: Option<String>,
+  pub recipient_ids: Vec<i32>, // TODO another way to do this? Maybe a UserMention belongs to Comment
+  pub form_id: Option<String>, // An optional front end ID, to tell which is coming back
 }
 
 #[derive(Deserialize)]
@@ -98,6 +98,7 @@ pub struct ResolveCommentReport {
 
 #[derive(Serialize, Deserialize, Clone, Debug)]
 pub struct ResolveCommentReportResponse {
+  // TODO this should probably return the view
   pub report_id: i32,
   pub resolved: bool,
 }
index ac7837c52c2198e46792a25f5ca13ac10de7f5e6..65ea0aaaff0a97b6ccf785541702488c6fb7bb9c 100644 (file)
@@ -57,7 +57,7 @@ pub struct BanFromCommunity {
   pub community_id: i32,
   pub user_id: i32,
   pub ban: bool,
-  pub remove_data: Option<bool>,
+  pub remove_data: bool,
   pub reason: Option<String>,
   pub expires: Option<i64>,
   pub auth: String,
index dc06a40cd1c05415353bf5b08b203998df6c8829..d19127384b773ab04864fd6e821aba4a4c5df388 100644 (file)
@@ -3,7 +3,6 @@ pub mod community;
 pub mod post;
 pub mod site;
 pub mod user;
-pub mod websocket;
 
 use diesel::PgConnection;
 use lemmy_db::{
index fe6a059e2ecf3fac070686041738f80b5c2782b1..ac29d8f7807d373ad0f24ad697bc141fbedffa93 100644 (file)
@@ -1,6 +1,6 @@
 use lemmy_db::views::{
   comment_view::CommentView,
-  community::{community_moderator_view::CommunityModeratorView, community_view::CommunityView},
+  community::community_moderator_view::CommunityModeratorView,
   post_report_view::PostReportView,
   post_view::PostView,
 };
@@ -31,7 +31,6 @@ pub struct GetPost {
 pub struct GetPostResponse {
   pub post_view: PostView,
   pub comments: Vec<CommentView>,
-  pub community: CommunityView,
   pub moderators: Vec<CommunityModeratorView>,
   pub online: usize,
 }
index 9209a54202cd2325e8c921800fd4d38c6dccee95..ff6c8a3912cb81a40b713043202d18ea8f89cea4 100644 (file)
@@ -1,5 +1,4 @@
 use lemmy_db::{
-  aggregates::site_aggregates::SiteAggregates,
   source::{category::*, user::*},
   views::{
     comment_view::CommentView,
@@ -101,16 +100,14 @@ pub struct GetSite {
   pub auth: Option<String>,
 }
 
-// TODO combine siteresponse and getsiteresponse
 #[derive(Serialize, Clone)]
 pub struct SiteResponse {
-  pub site: SiteView,
+  pub site_view: SiteView,
 }
 
 #[derive(Serialize)]
 pub struct GetSiteResponse {
-  pub site: Option<SiteView>, // Because the site might not be set up yet
-  pub counts: SiteAggregates,
+  pub site_view: Option<SiteView>, // Because the site might not be set up yet
   pub admins: Vec<UserViewSafe>,
   pub banned: Vec<UserViewSafe>,
   pub online: usize,
index f73d63f99303284f579eac3ebe2d9dcd40f6a368..52871696cf71cabd7ce4b080fe94280604536283 100644 (file)
@@ -48,8 +48,8 @@ pub struct CaptchaResponse {
 pub struct SaveUserSettings {
   pub show_nsfw: bool,
   pub theme: String,
-  pub default_sort_type: i16,
-  pub default_listing_type: i16,
+  pub default_sort_type: String,
+  pub default_listing_type: String,
   pub lang: String,
   pub avatar: Option<String>,
   pub banner: Option<String>,
@@ -84,8 +84,8 @@ pub struct GetUserDetails {
 
 #[derive(Serialize)]
 pub struct GetUserDetailsResponse {
-  pub user: Option<UserViewSafe>,
-  pub user_dangerous: Option<UserViewDangerous>,
+  pub user_view: Option<UserViewSafe>,
+  pub user_view_dangerous: Option<UserViewDangerous>,
   pub follows: Vec<CommunityFollowerView>,
   pub moderates: Vec<CommunityModeratorView>,
   pub comments: Vec<CommentView>,
@@ -123,7 +123,7 @@ pub struct AddAdminResponse {
 pub struct BanUser {
   pub user_id: i32,
   pub ban: bool,
-  pub remove_data: Option<bool>,
+  pub remove_data: bool,
   pub reason: Option<String>,
   pub expires: Option<i64>,
   pub auth: String,
@@ -131,7 +131,7 @@ pub struct BanUser {
 
 #[derive(Serialize, Clone)]
 pub struct BanUserResponse {
-  pub user: UserViewSafe,
+  pub user_view: UserViewSafe,
   pub banned: bool,
 }
 
@@ -224,12 +224,12 @@ pub struct GetPrivateMessages {
 
 #[derive(Serialize, Clone)]
 pub struct PrivateMessagesResponse {
-  pub messages: Vec<PrivateMessageView>,
+  pub private_messages: Vec<PrivateMessageView>,
 }
 
 #[derive(Serialize, Clone)]
 pub struct PrivateMessageResponse {
-  pub message: PrivateMessageView,
+  pub private_message_view: PrivateMessageView,
 }
 
 #[derive(Deserialize, Debug)]
diff --git a/lemmy_structs/src/websocket.rs b/lemmy_structs/src/websocket.rs
deleted file mode 100644 (file)
index 8b13789..0000000
+++ /dev/null
@@ -1 +0,0 @@
-
index 4bbee76151b27769b3d99517fdb5d68114c773c9..2a2aa97d5fc6f5a6a4ae248be9d2d801fabe6388 100644 (file)
@@ -1,10 +1,12 @@
 -- Site aggregates
 drop table site_aggregates;
+drop trigger site_aggregates_site on site;
 drop trigger site_aggregates_user on user_;
 drop trigger site_aggregates_post on post;
 drop trigger site_aggregates_comment on comment;
 drop trigger site_aggregates_community on community;
 drop function 
+  site_aggregates_site,
   site_aggregates_user,
   site_aggregates_post,
   site_aggregates_comment,
index b957234762e7aa8415ffd19526b34eab56bc5505..cc76a5c7591aa69a0bcaa93ab22927db8e3b6967 100644 (file)
@@ -1,17 +1,38 @@
 -- Add site aggregates
 create table site_aggregates (
   id serial primary key,
-  users bigint not null,
-  posts bigint not null,
-  comments bigint not null,
-  communities bigint not null
+  site_id int references site on update cascade on delete cascade not null,
+  users bigint not null default 0,
+  posts bigint not null default 0,
+  comments bigint not null default 0,
+  communities bigint not null default 0
 );
 
-insert into site_aggregates (users, posts, comments, communities)
-  select ( select coalesce(count(*), 0) from user_) as users, 
+insert into site_aggregates (site_id, users, posts, comments, communities)
+  select id as site_id,
+  ( select coalesce(count(*), 0) from user_) as users, 
   ( select coalesce(count(*), 0) from post) as posts,
   ( select coalesce(count(*), 0) from comment) as comments,
-  ( select coalesce(count(*), 0) from community) as communities;
+  ( select coalesce(count(*), 0) from community) as communities
+  from site;
+
+-- initial site add
+create function site_aggregates_site()
+returns trigger language plpgsql
+as $$
+begin
+  IF (TG_OP = 'INSERT') THEN
+    insert into site_aggregates (site_id) values (NEW.id);
+  ELSIF (TG_OP = 'DELETE') THEN
+    delete from site_aggregates where site_id = OLD.id;
+  END IF;
+  return null;
+end $$;
+
+create trigger site_aggregates_site
+after insert or delete on site
+for each row
+execute procedure site_aggregates_site();
 
 -- Add site aggregate triggers
 -- user