diff --git a/.github/ISSUE_TEMPLATE/QUESTION.yml b/.github/ISSUE_TEMPLATE/QUESTION.yml index 734937e9a..d9a9badb7 100644 --- a/.github/ISSUE_TEMPLATE/QUESTION.yml +++ b/.github/ISSUE_TEMPLATE/QUESTION.yml @@ -6,12 +6,12 @@ body: - type: markdown attributes: value: | - Have a question about Lemmy's UI? + Have a question about Lemmy? Please check the docs first: https://join-lemmy.org/docs/en/index.html - type: textarea id: question attributes: label: Question - description: What's the question you have about Lemmy's UI? + description: What's the question you have about Lemmy? validations: required: true diff --git a/.woodpecker.yml b/.woodpecker.yml index a3c1f1194..0c7efbd85 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -29,7 +29,7 @@ variables: # recursive: true # submodule_update_remote: true -pipeline: +steps: prepare_repo: image: alpine:3 commands: @@ -38,10 +38,35 @@ pipeline: - git submodule update prettier_check: + group: format image: tmknom/prettier:3.0.0 commands: - prettier -c . '!**/volumes' '!**/dist' '!target' '!**/translations' + toml_fmt: + group: format + image: tamasfe/taplo:0.8.1 + commands: + - taplo format --check + + sql_fmt: + group: format + image: backplane/pgformatter:latest + commands: + - ./scripts/sql_format_check.sh + + cargo_fmt: + group: format + image: *muslrust_image + environment: + # store cargo data in repo folder so that it gets cached between steps + CARGO_HOME: .cargo + commands: + # need make existing toolchain available + - cp -n ~/.cargo . -r + - rustup toolchain install nightly-2023-07-10 --no-self-update --profile minimal --component rustfmt + - cargo +nightly-2023-07-10 fmt -- --check + restore-cache: image: meltwater/drone-cache:v1 pull: true @@ -66,35 +91,6 @@ pipeline: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] when: *slow_check_paths - toml_fmt: - image: tamasfe/taplo:0.8.1 - commands: - - taplo format --check - - cargo_fmt: - image: *muslrust_image - environment: - # store cargo data in repo folder so that it gets cached between steps - CARGO_HOME: .cargo - commands: - # need make existing toolchain available - - cp -n ~/.cargo . -r - - rustup toolchain install nightly-2023-07-10 - - rustup component add rustfmt --toolchain nightly-2023-07-10 - - cargo +nightly-2023-07-10 fmt -- --check - - sql_fmt: - image: alpine:3 - commands: - - apk add bash wget perl make git - - wget https://github.com/darold/pgFormatter/archive/refs/tags/v5.5.tar.gz - - tar xzf v5.5.tar.gz - - cd pgFormatter-5.5 - - perl Makefile.PL - - make && make install - - cd .. - - ./scripts/./sql_format_check.sh - # make sure api builds with default features (used by other crates relying on lemmy api) check_api_common_default_features: image: *muslrust_image @@ -176,7 +172,17 @@ pipeline: -D clippy::indexing_slicing when: *slow_check_paths + cargo_build: + image: *muslrust_image + environment: + CARGO_HOME: .cargo + commands: + - cargo build + - mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server + when: *slow_check_paths + cargo_test: + group: tests image: *muslrust_image environment: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy @@ -187,16 +193,8 @@ pipeline: - cargo test --workspace --no-fail-fast when: *slow_check_paths - cargo_build: - image: *muslrust_image - environment: - CARGO_HOME: .cargo - commands: - - cargo build - - mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server - when: *slow_check_paths - run_federation_tests: + group: tests image: node:alpine environment: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432 @@ -231,7 +229,9 @@ pipeline: - "api_tests/node_modules" secrets: [MINIO_ENDPOINT, MINIO_WRITE_USER, MINIO_WRITE_PASSWORD, MINIO_BUCKET] - when: *slow_check_paths + when: + - event: push + branch: main publish_release_docker: image: woodpeckerci/plugin-docker-buildx @@ -263,7 +263,7 @@ pipeline: image: alpine:3 commands: - apk add curl - - "curl -d'Lemmy CI build failed: ${CI_BUILD_LINK}' ntfy.sh/lemmy_drone_ci" + - "curl -d'Lemmy CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci" when: status: [failure] diff --git a/RELEASES.md b/RELEASES.md index a81512800..bd56985a5 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,51 @@ +# Lemmy v0.18.4 Release (2023-08-08) + +## What is Lemmy? + +Lemmy is a self-hosted social link aggregation and discussion platform. It is completely free and open, and not controlled by any company. This means that there is no advertising, tracking, or secret algorithms. Content is organized into communities, so it is easy to subscribe to topics that you are interested in, and ignore others. Voting is used to bring the most interesting items to the top. + +## Major Changes + +This version fixes the problem of comment context not loading properly. It also fixes a couple other bugs. + +## Support development + +@dessalines and @nutomic are working full-time on Lemmy to integrate community contributions, fix bugs, optimize performance and much more. This work is funded exclusively through donations. + +If you like using Lemmy, and want to make sure that we will always be available to work full time building it, consider [donating to support its development](https://join-lemmy.org/donate). No one likes recurring donations, but they’ve proven to be the only way that open-source software like Lemmy can stay independent and alive. + +- [Liberapay](https://liberapay.com/Lemmy) (preferred option) +- [Open Collective](https://opencollective.com/lemmy) +- [Patreon](https://www.patreon.com/dessalines) +- [Cryptocurrency](https://join-lemmy.org/donate) (scroll to bottom of page) + +## Upgrade instructions + +Follow the upgrade instructions for [ansible](https://github.com/LemmyNet/lemmy-ansible#upgrading) or [docker](https://join-lemmy.org/docs/en/administration/install_docker.html#updating). There are no config or API changes with this release. + +If you need help with the upgrade, you can ask in our [support forum](https://lemmy.ml/c/lemmy_support) or on the [Matrix Chat](https://matrix.to/#/#lemmy-admin-support-topics:discuss.online). + +## Changes + +### Lemmy + +- Fix fetch instance software version from nodeinfo ([#3772](https://github.com/LemmyNet/lemmy/issues/3772)) +- Correct logic to meet join-lemmy requirement, don't have closed signups. Allows Open and Applications. ([#3761](https://github.com/LemmyNet/lemmy/issues/3761)) +- Fix ordering when doing a comment_parent type `list_comments` ([#3823](https://github.com/LemmyNet/lemmy/issues/3823)) + +### Lemmy-UI + +- Mark post as read when clicking "Expand here" on the preview image on the post listing page ([#1600](https://github.com/LemmyNet/lemmy/issues/1600)) ([#1978](https://github.com/LemmyNet/lemmy/issues/1978)) +- Update translation submodule ([#2023](https://github.com/LemmyNet/lemmy/issues/2023)) +- Fix comment insertion from context views. Fixes #2030 ([#2031](https://github.com/LemmyNet/lemmy/issues/2031)) +- Fix password autocomplete ([#2033](https://github.com/LemmyNet/lemmy/issues/2033)) +- Fix suggested title " " spaces ([#2037](https://github.com/LemmyNet/lemmy/issues/2037)) +- Expanded the RegEx to check if the title contains new line caracters. Should fix issue #1962 ([#1965](https://github.com/LemmyNet/lemmy/issues/1965)) +- ES-Lint tweak ([#2001](https://github.com/LemmyNet/lemmy/issues/2001)) +- Upgrading deps, running prettier. ([#1987](https://github.com/LemmyNet/lemmy/issues/1987)) +- Fix document title of admin settings being overwritten by tagline and emoji forms ([#2003](https://github.com/LemmyNet/lemmy/issues/2003)) +- Use proper modifier key in markdown text input on macOS ([#1995](https://github.com/LemmyNet/lemmy/issues/1995)) + # Lemmy v0.18.3 Release (2023-07-28) ## What is Lemmy? diff --git a/crates/api/src/comment/distinguish.rs b/crates/api/src/comment/distinguish.rs index 540c19a3d..7db9a58f8 100644 --- a/crates/api/src/comment/distinguish.rs +++ b/crates/api/src/comment/distinguish.rs @@ -38,9 +38,10 @@ pub async fn distinguish_comment( // Update the Comment let comment_id = data.comment_id; - let form = CommentUpdateForm::builder() - .distinguished(Some(data.distinguished)) - .build(); + let form = CommentUpdateForm { + distinguished: Some(data.distinguished), + ..Default::default() + }; Comment::update(&mut context.pool(), comment_id, &form) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; @@ -52,6 +53,5 @@ pub async fn distinguish_comment( Ok(Json(CommentResponse { comment_view, recipient_ids: Vec::new(), - form_id: None, })) } diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index 13122b4be..af013f283 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -89,7 +89,6 @@ pub async fn like_comment( context.deref(), comment_id, Some(local_user_view), - None, recipient_ids, ) .await?, diff --git a/crates/api/src/comment/save.rs b/crates/api/src/comment/save.rs index 8c9d90555..f2c926f17 100644 --- a/crates/api/src/comment/save.rs +++ b/crates/api/src/comment/save.rs @@ -40,6 +40,5 @@ pub async fn save_comment( Ok(Json(CommentResponse { comment_view, recipient_ids: Vec::new(), - form_id: None, })) } diff --git a/crates/api/src/comment_report/list.rs b/crates/api/src/comment_report/list.rs index 0ca093c74..3f6f160c8 100644 --- a/crates/api/src/comment_report/list.rs +++ b/crates/api/src/comment_report/list.rs @@ -17,7 +17,7 @@ pub async fn list_comment_reports( let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; let community_id = data.community_id; - let unresolved_only = data.unresolved_only; + let unresolved_only = data.unresolved_only.unwrap_or_default(); let page = data.page; let limit = data.limit; diff --git a/crates/api/src/community/block.rs b/crates/api/src/community/block.rs index f807574ed..f27b7c01b 100644 --- a/crates/api/src/community/block.rs +++ b/crates/api/src/community/block.rs @@ -52,7 +52,7 @@ pub async fn block_community( } let community_view = - CommunityView::read(&mut context.pool(), community_id, Some(person_id), None).await?; + CommunityView::read(&mut context.pool(), community_id, Some(person_id), false).await?; ActivityChannel::submit_activity( SendActivityData::FollowCommunity( diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs index 8fea2625d..2a50a94ed 100644 --- a/crates/api/src/community/follow.rs +++ b/crates/api/src/community/follow.rs @@ -61,7 +61,7 @@ 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), None).await?; + CommunityView::read(&mut context.pool(), community_id, Some(person_id), false).await?; let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?; Ok(Json(CommunityResponse { diff --git a/crates/api/src/community/hide.rs b/crates/api/src/community/hide.rs index ce437ad99..10ca6372a 100644 --- a/crates/api/src/community/hide.rs +++ b/crates/api/src/community/hide.rs @@ -25,9 +25,10 @@ pub async fn hide_community( let local_user_view = local_user_view_from_jwt(&data.auth, &context).await?; is_admin(&local_user_view)?; - let community_form = CommunityUpdateForm::builder() - .hidden(Some(data.hidden)) - .build(); + let community_form = CommunityUpdateForm { + hidden: Some(data.hidden), + ..Default::default() + }; let mod_hide_community_form = ModHideCommunityForm { community_id: data.community_id, diff --git a/crates/api/src/community/transfer.rs b/crates/api/src/community/transfer.rs index 2b6579c4d..c63c25750 100644 --- a/crates/api/src/community/transfer.rs +++ b/crates/api/src/community/transfer.rs @@ -84,7 +84,7 @@ impl Perform for TransferCommunity { 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), None) + CommunityView::read(&mut context.pool(), community_id, Some(person_id), false) .await .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?; diff --git a/crates/api/src/lib.rs b/crates/api/src/lib.rs index cc5fb8e8e..1b7b32154 100644 --- a/crates/api/src/lib.rs +++ b/crates/api/src/lib.rs @@ -40,7 +40,7 @@ pub(crate) fn captcha_as_wav_base64(captcha: &Captcha) -> Result Resul check_slurs(reason, slur_regex)?; if reason.is_empty() { - return Err(LemmyErrorType::ReportReasonRequired)?; + Err(LemmyErrorType::ReportReasonRequired)?; } if reason.chars().count() > 1000 { - return Err(LemmyErrorType::ReportTooLong)?; + Err(LemmyErrorType::ReportTooLong)?; } Ok(()) } diff --git a/crates/api/src/local_user/add_admin.rs b/crates/api/src/local_user/add_admin.rs index 0b478ea92..81ec588f0 100644 --- a/crates/api/src/local_user/add_admin.rs +++ b/crates/api/src/local_user/add_admin.rs @@ -32,7 +32,10 @@ impl Perform for AddAdmin { let added_admin = Person::update( &mut context.pool(), added_person_id, - &PersonUpdateForm::builder().admin(Some(added)).build(), + &PersonUpdateForm { + admin: Some(added), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?; diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs index 6e99ef250..490a51448 100644 --- a/crates/api/src/local_user/ban_person.rs +++ b/crates/api/src/local_user/ban_person.rs @@ -35,10 +35,11 @@ pub async fn ban_from_site( let person = Person::update( &mut context.pool(), data.person_id, - &PersonUpdateForm::builder() - .banned(Some(data.ban)) - .ban_expires(Some(expires)) - .build(), + &PersonUpdateForm { + banned: Some(data.ban), + ban_expires: Some(expires), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateUser)?; diff --git a/crates/api/src/local_user/notifications/list_mentions.rs b/crates/api/src/local_user/notifications/list_mentions.rs index 10d24ff8f..46b11f605 100644 --- a/crates/api/src/local_user/notifications/list_mentions.rs +++ b/crates/api/src/local_user/notifications/list_mentions.rs @@ -23,9 +23,9 @@ impl Perform for GetPersonMentions { let sort = data.sort; let page = data.page; let limit = data.limit; - let unread_only = data.unread_only; + let unread_only = data.unread_only.unwrap_or_default(); let person_id = Some(local_user_view.person.id); - let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts); + let show_bot_accounts = local_user_view.local_user.show_bot_accounts; let mentions = PersonMentionQuery { recipient_id: person_id, diff --git a/crates/api/src/local_user/notifications/list_replies.rs b/crates/api/src/local_user/notifications/list_replies.rs index 8c7f3059b..370cd61b4 100644 --- a/crates/api/src/local_user/notifications/list_replies.rs +++ b/crates/api/src/local_user/notifications/list_replies.rs @@ -20,9 +20,9 @@ impl Perform for GetReplies { let sort = data.sort; let page = data.page; let limit = data.limit; - let unread_only = data.unread_only; + let unread_only = data.unread_only.unwrap_or_default(); let person_id = Some(local_user_view.person.id); - let show_bot_accounts = Some(local_user_view.local_user.show_bot_accounts); + let show_bot_accounts = local_user_view.local_user.show_bot_accounts; let replies = CommentReplyQuery { recipient_id: person_id, diff --git a/crates/api/src/local_user/save_settings.rs b/crates/api/src/local_user/save_settings.rs index 152c11ad1..946b5e8b6 100644 --- a/crates/api/src/local_user/save_settings.rs +++ b/crates/api/src/local_user/save_settings.rs @@ -90,14 +90,15 @@ impl Perform for SaveUserSettings { let default_sort_type = data.default_sort_type; let theme = sanitize_html_opt(&data.theme); - let person_form = PersonUpdateForm::builder() - .display_name(display_name) - .bio(bio) - .matrix_user_id(matrix_user_id) - .bot_account(data.bot_account) - .avatar(avatar) - .banner(banner) - .build(); + let person_form = PersonUpdateForm { + display_name, + bio, + matrix_user_id, + bot_account: data.bot_account, + avatar, + banner, + ..Default::default() + }; Person::update(&mut context.pool(), person_id, &person_form) .await @@ -121,26 +122,27 @@ impl Perform for SaveUserSettings { (None, None) }; - let local_user_form = LocalUserUpdateForm::builder() - .email(email) - .show_avatars(data.show_avatars) - .show_read_posts(data.show_read_posts) - .show_new_post_notifs(data.show_new_post_notifs) - .send_notifications_to_email(data.send_notifications_to_email) - .show_nsfw(data.show_nsfw) - .blur_nsfw(data.blur_nsfw) - .auto_expand(data.auto_expand) - .show_bot_accounts(data.show_bot_accounts) - .show_scores(data.show_scores) - .default_sort_type(default_sort_type) - .default_listing_type(default_listing_type) - .theme(theme) - .interface_language(data.interface_language.clone()) - .totp_2fa_secret(totp_2fa_secret) - .totp_2fa_url(totp_2fa_url) - .open_links_in_new_tab(data.open_links_in_new_tab) - .infinite_scroll_enabled(data.infinite_scroll_enabled) - .build(); + let local_user_form = LocalUserUpdateForm { + email, + show_avatars: data.show_avatars, + show_read_posts: data.show_read_posts, + show_new_post_notifs: data.show_new_post_notifs, + send_notifications_to_email: data.send_notifications_to_email, + show_nsfw: data.show_nsfw, + blur_nsfw: data.blur_nsfw, + auto_expand: data.auto_expand, + show_bot_accounts: data.show_bot_accounts, + show_scores: data.show_scores, + default_sort_type, + default_listing_type, + theme, + interface_language: data.interface_language.clone(), + totp_2fa_secret, + totp_2fa_url, + open_links_in_new_tab: data.open_links_in_new_tab, + infinite_scroll_enabled: data.infinite_scroll_enabled, + ..Default::default() + }; let local_user_res = LocalUser::update(&mut context.pool(), local_user_id, &local_user_form).await; diff --git a/crates/api/src/local_user/verify_email.rs b/crates/api/src/local_user/verify_email.rs index a0c4763a6..a15743ea4 100644 --- a/crates/api/src/local_user/verify_email.rs +++ b/crates/api/src/local_user/verify_email.rs @@ -23,12 +23,13 @@ impl Perform for VerifyEmail { .await .with_lemmy_type(LemmyErrorType::TokenNotFound)?; - let form = LocalUserUpdateForm::builder() + let form = LocalUserUpdateForm { // necessary in case this is a new signup - .email_verified(Some(true)) + email_verified: Some(true), // necessary in case email of an existing user was changed - .email(Some(Some(verification.email))) - .build(); + email: Some(Some(verification.email)), + ..Default::default() + }; let local_user_id = verification.local_user_id; LocalUser::update(&mut context.pool(), local_user_id, &form).await?; diff --git a/crates/api/src/post/feature.rs b/crates/api/src/post/feature.rs index 5e18c2b64..02b9551a9 100644 --- a/crates/api/src/post/feature.rs +++ b/crates/api/src/post/feature.rs @@ -56,13 +56,15 @@ pub async fn feature_post( // Update the post let post_id = data.post_id; let new_post: PostUpdateForm = if data.feature_type == PostFeatureType::Community { - PostUpdateForm::builder() - .featured_community(Some(data.featured)) - .build() + PostUpdateForm { + featured_community: Some(data.featured), + ..Default::default() + } } else { - PostUpdateForm::builder() - .featured_local(Some(data.featured)) - .build() + PostUpdateForm { + featured_local: Some(data.featured), + ..Default::default() + } }; let post = Post::update(&mut context.pool(), post_id, &new_post).await?; diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs index 45ec3317f..b2ba9b3d1 100644 --- a/crates/api/src/post/lock.rs +++ b/crates/api/src/post/lock.rs @@ -53,7 +53,10 @@ pub async fn lock_post( let post = Post::update( &mut context.pool(), post_id, - &PostUpdateForm::builder().locked(Some(locked)).build(), + &PostUpdateForm { + locked: Some(locked), + ..Default::default() + }, ) .await?; diff --git a/crates/api/src/post/mark_read.rs b/crates/api/src/post/mark_read.rs index 0b777a7e1..99f539a92 100644 --- a/crates/api/src/post/mark_read.rs +++ b/crates/api/src/post/mark_read.rs @@ -28,7 +28,7 @@ impl Perform for MarkPostAsRead { } // Fetch it - let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), None).await?; + let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), false).await?; Ok(Self::Response { post_view }) } diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs index aa5d0c10e..d9965dc75 100644 --- a/crates/api/src/post/save.rs +++ b/crates/api/src/post/save.rs @@ -38,7 +38,7 @@ impl Perform for SavePost { 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), None).await?; + let post_view = PostView::read(&mut context.pool(), post_id, Some(person_id), false).await?; // Mark the post as read mark_post_as_read(person_id, post_id, &mut context.pool()).await?; diff --git a/crates/api/src/post_report/create.rs b/crates/api/src/post_report/create.rs index 68eb8f7bd..d4100a84e 100644 --- a/crates/api/src/post_report/create.rs +++ b/crates/api/src/post_report/create.rs @@ -36,7 +36,7 @@ pub async fn create_post_report( let person_id = local_user_view.person.id; let post_id = data.post_id; - let post_view = PostView::read(&mut context.pool(), post_id, None, None).await?; + let post_view = PostView::read(&mut context.pool(), post_id, None, false).await?; check_community_ban(person_id, post_view.community.id, &mut context.pool()).await?; diff --git a/crates/api/src/post_report/list.rs b/crates/api/src/post_report/list.rs index a0d909681..f5edab703 100644 --- a/crates/api/src/post_report/list.rs +++ b/crates/api/src/post_report/list.rs @@ -23,7 +23,7 @@ impl Perform for ListPostReports { let local_user_view = local_user_view_from_jwt(&data.auth, context).await?; let community_id = data.community_id; - let unresolved_only = data.unresolved_only; + let unresolved_only = data.unresolved_only.unwrap_or_default(); let page = data.page; let limit = data.limit; diff --git a/crates/api/src/private_message/mark_read.rs b/crates/api/src/private_message/mark_read.rs index cca37fde4..54fb4790c 100644 --- a/crates/api/src/private_message/mark_read.rs +++ b/crates/api/src/private_message/mark_read.rs @@ -38,7 +38,10 @@ impl Perform for MarkPrivateMessageAsRead { PrivateMessage::update( &mut context.pool(), private_message_id, - &PrivateMessageUpdateForm::builder().read(Some(read)).build(), + &PrivateMessageUpdateForm { + read: Some(read), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?; diff --git a/crates/api/src/private_message_report/list.rs b/crates/api/src/private_message_report/list.rs index 8b4e50767..c476b1f45 100644 --- a/crates/api/src/private_message_report/list.rs +++ b/crates/api/src/private_message_report/list.rs @@ -18,7 +18,7 @@ impl Perform for ListPrivateMessageReports { is_admin(&local_user_view)?; - let unresolved_only = self.unresolved_only; + let unresolved_only = self.unresolved_only.unwrap_or_default(); let page = self.page; let limit = self.limit; let private_message_reports = PrivateMessageReportQuery { diff --git a/crates/api/src/site/leave_admin.rs b/crates/api/src/site/leave_admin.rs index 3781c73f2..570f9d52c 100644 --- a/crates/api/src/site/leave_admin.rs +++ b/crates/api/src/site/leave_admin.rs @@ -43,7 +43,10 @@ impl Perform for LeaveAdmin { Person::update( &mut context.pool(), person_id, - &PersonUpdateForm::builder().admin(Some(false)).build(), + &PersonUpdateForm { + admin: Some(false), + ..Default::default() + }, ) .await?; diff --git a/crates/api/src/site/registration_applications/approve.rs b/crates/api/src/site/registration_applications/approve.rs index 227f93243..eb0fb0323 100644 --- a/crates/api/src/site/registration_applications/approve.rs +++ b/crates/api/src/site/registration_applications/approve.rs @@ -40,9 +40,10 @@ impl Perform for ApproveRegistrationApplication { RegistrationApplication::update(&mut context.pool(), app_id, &app_form).await?; // Update the local_user row - let local_user_form = LocalUserUpdateForm::builder() - .accepted_application(Some(data.approve)) - .build(); + let local_user_form = LocalUserUpdateForm { + accepted_application: Some(data.approve), + ..Default::default() + }; let approved_user_id = registration_application.local_user_id; LocalUser::update(&mut context.pool(), approved_user_id, &local_user_form).await?; diff --git a/crates/api/src/site/registration_applications/list.rs b/crates/api/src/site/registration_applications/list.rs index 433cee425..aeff9f97f 100644 --- a/crates/api/src/site/registration_applications/list.rs +++ b/crates/api/src/site/registration_applications/list.rs @@ -22,8 +22,8 @@ impl Perform for ListRegistrationApplications { // Make sure user is an admin is_admin(&local_user_view)?; - let unread_only = data.unread_only; - let verified_email_only = Some(local_site.require_email_verification); + let unread_only = data.unread_only.unwrap_or_default(); + let verified_email_only = local_site.require_email_verification; let page = data.page; let limit = data.limit; diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index 8d3bcda1a..e0d399764 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -26,7 +26,6 @@ pub async fn build_comment_response( context: &LemmyContext, comment_id: CommentId, local_user_view: Option, - form_id: Option, recipient_ids: Vec, ) -> Result { let person_id = local_user_view.map(|l| l.person.id); @@ -34,7 +33,6 @@ pub async fn build_comment_response( Ok(CommentResponse { comment_view, recipient_ids, - form_id, }) } @@ -52,7 +50,7 @@ pub async fn build_community_response( &mut context.pool(), community_id, Some(person_id), - Some(is_mod_or_admin), + is_mod_or_admin, ) .await?; let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?; @@ -76,7 +74,7 @@ pub async fn build_post_response( &mut context.pool(), post_id, Some(person_id), - Some(is_mod_or_admin), + is_mod_or_admin, ) .await?; Ok(Json(PostResponse { post_view })) diff --git a/crates/api_common/src/comment.rs b/crates/api_common/src/comment.rs index 380e9f0ca..ec9ca1328 100644 --- a/crates/api_common/src/comment.rs +++ b/crates/api_common/src/comment.rs @@ -20,8 +20,6 @@ pub struct CreateComment { pub post_id: PostId, pub parent_id: Option, pub language_id: Option, - /// An optional front-end ID, to help UIs determine where the comment should go. - pub form_id: Option, pub auth: Sensitive, } @@ -44,7 +42,6 @@ pub struct EditComment { pub comment_id: CommentId, pub content: Option, pub language_id: Option, - pub form_id: Option, pub auth: Sensitive, } @@ -100,8 +97,6 @@ pub struct SaveComment { pub struct CommentResponse { pub comment_view: CommentView, pub recipient_ids: Vec, - /// An optional front end ID, to tell which is coming back - pub form_id: Option, } #[derive(Debug, Serialize, Deserialize, Clone, Default)] @@ -131,6 +126,8 @@ pub struct GetComments { pub post_id: Option, pub parent_id: Option, pub saved_only: Option, + pub liked_only: Option, + pub disliked_only: Option, pub auth: Option>, } diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index 01a7db9ce..e511d2798 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -75,6 +75,8 @@ pub struct GetPosts { pub community_id: Option, pub community_name: Option, pub saved_only: Option, + pub liked_only: Option, + pub disliked_only: Option, pub moderator_view: Option, pub auth: Option>, } diff --git a/crates/api_common/src/private_message.rs b/crates/api_common/src/private_message.rs index f72712cdf..d27c4f659 100644 --- a/crates/api_common/src/private_message.rs +++ b/crates/api_common/src/private_message.rs @@ -55,6 +55,7 @@ pub struct GetPrivateMessages { pub unread_only: Option, pub page: Option, pub limit: Option, + pub creator_id: Option, pub auth: Sensitive, } diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index 82126887a..b62514c02 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -44,7 +44,7 @@ fn html_to_site_metadata(html_bytes: &[u8], url: &Url) -> Result") { - return Err(LemmyErrorType::SiteMetadataPageIsNotDoctypeHtml)?; + Err(LemmyErrorType::SiteMetadataPageIsNotDoctypeHtml)?; } let mut page = HTML::from_string(html.to_string(), None)?; diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 6bdc30285..4d434afcd 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -79,7 +79,7 @@ pub async fn is_mod_or_admin_opt( pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> { if !local_user_view.person.admin { - return Err(LemmyErrorType::NotAnAdmin)?; + Err(LemmyErrorType::NotAnAdmin)?; } Ok(()) } @@ -94,7 +94,7 @@ pub fn is_top_mod( .map(|cm| cm.moderator.id) .unwrap_or(PersonId(0)) { - return Err(LemmyErrorType::NotTopMod)?; + Err(LemmyErrorType::NotTopMod)?; } Ok(()) } @@ -181,12 +181,12 @@ pub fn check_user_valid( ) -> Result<(), LemmyError> { // Check for a site ban if is_banned(banned, ban_expires) { - return Err(LemmyErrorType::SiteBan)?; + Err(LemmyErrorType::SiteBan)?; } // check for account deletion if deleted { - return Err(LemmyErrorType::Deleted)?; + Err(LemmyErrorType::Deleted)?; } Ok(()) @@ -250,7 +250,7 @@ pub async fn check_person_block( #[tracing::instrument(skip_all)] pub fn check_downvotes_enabled(score: i16, local_site: &LocalSite) -> Result<(), LemmyError> { if score == -1 && !local_site.enable_downvotes { - return Err(LemmyErrorType::DownvotesAreDisabled)?; + Err(LemmyErrorType::DownvotesAreDisabled)?; } Ok(()) } @@ -261,7 +261,7 @@ pub fn check_private_instance( local_site: &LocalSite, ) -> Result<(), LemmyError> { if local_user_view.is_none() && local_site.private_instance { - return Err(LemmyErrorType::InstanceIsPrivate)?; + Err(LemmyErrorType::InstanceIsPrivate)?; } Ok(()) } @@ -522,7 +522,7 @@ pub fn check_private_instance_and_federation_enabled( local_site: &LocalSite, ) -> Result<(), LemmyError> { if local_site.private_instance && local_site.federation_enabled { - return Err(LemmyErrorType::CantEnablePrivateInstanceAndFederationTogether)?; + Err(LemmyErrorType::CantEnablePrivateInstanceAndFederationTogether)?; } Ok(()) } @@ -596,10 +596,11 @@ pub async fn remove_user_data( Person::update( pool, banned_person_id, - &PersonUpdateForm::builder() - .avatar(Some(None)) - .banner(Some(None)) - .build(), + &PersonUpdateForm { + avatar: Some(None), + banner: Some(None), + ..Default::default() + }, ) .await?; @@ -625,7 +626,10 @@ pub async fn remove_user_data( Community::update( pool, community_id, - &CommunityUpdateForm::builder().removed(Some(true)).build(), + &CommunityUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await?; @@ -642,10 +646,11 @@ pub async fn remove_user_data( Community::update( pool, community_id, - &CommunityUpdateForm::builder() - .icon(Some(None)) - .banner(Some(None)) - .build(), + &CommunityUpdateForm { + icon: Some(None), + banner: Some(None), + ..Default::default() + }, ) .await?; } @@ -679,7 +684,10 @@ pub async fn remove_user_data_in_community( Comment::update( pool, comment_id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await?; } @@ -797,12 +805,14 @@ pub fn generate_moderators_url(community_id: &DbUrl) -> Result String { - let sanitized = ammonia::Builder::default() + ammonia::Builder::default() .rm_tags(&["a", "img"]) .clean(data) - .to_string(); - // restore markdown quotes - sanitized.replace(">", ">") + .to_string() + // restore markdown quotes + .replace(">", ">") + // restore white space + .replace(" ", " ") } pub fn sanitize_html_opt(data: &Option) -> Option { @@ -839,5 +849,7 @@ mod tests { assert_eq!(sanitized, " hello"); let sanitized = sanitize_html(" test"); assert_eq!(sanitized, " test"); + let sanitized = sanitize_html("Hello World"); + assert_eq!(sanitized, "Hello World"); } } diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 8b8afc8f1..33e480a9b 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -129,7 +129,10 @@ pub async fn create_comment( let updated_comment = Comment::update( &mut context.pool(), inserted_comment_id, - &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(), + &CommentUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntCreateComment)?; @@ -198,7 +201,6 @@ pub async fn create_comment( &context, inserted_comment.id, Some(local_user_view), - data.form_id.clone(), recipient_ids, ) .await?, diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index 10063c66f..96c22b604 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -49,7 +49,10 @@ pub async fn delete_comment( let updated_comment = Comment::update( &mut context.pool(), comment_id, - &CommentUpdateForm::builder().deleted(Some(deleted)).build(), + &CommentUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; @@ -82,7 +85,6 @@ pub async fn delete_comment( &context, updated_comment_id, Some(local_user_view), - None, recipient_ids, ) .await?, diff --git a/crates/api_crud/src/comment/read.rs b/crates/api_crud/src/comment/read.rs index 4ade60df5..5f07f7496 100644 --- a/crates/api_crud/src/comment/read.rs +++ b/crates/api_crud/src/comment/read.rs @@ -19,6 +19,6 @@ pub async fn get_comment( check_private_instance(&local_user_view, &local_site)?; Ok(Json( - build_comment_response(&context, data.id, local_user_view, None, vec![]).await?, + build_comment_response(&context, data.id, local_user_view, vec![]).await?, )) } diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index b20712986..c18a8c5b7 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -10,10 +10,11 @@ use lemmy_api_common::{ use lemmy_db_schema::{ source::{ comment::{Comment, CommentUpdateForm}, + comment_report::CommentReport, moderator::{ModRemoveComment, ModRemoveCommentForm}, post::Post, }, - traits::Crud, + traits::{Crud, Reportable}, }; use lemmy_db_views::structs::CommentView; use lemmy_utils::error::{LemmyError, LemmyErrorExt, LemmyErrorType}; @@ -48,11 +49,17 @@ pub async fn remove_comment( let updated_comment = Comment::update( &mut context.pool(), comment_id, - &CommentUpdateForm::builder().removed(Some(removed)).build(), + &CommentUpdateForm { + removed: Some(removed), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; + CommentReport::resolve_all_for_object(&mut context.pool(), comment_id, local_user_view.person.id) + .await?; + // Mod tables let form = ModRemoveCommentForm { mod_person_id: local_user_view.person.id, @@ -91,7 +98,6 @@ pub async fn remove_comment( &context, updated_comment_id, Some(local_user_view), - None, recipient_ids, ) .await?, diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index c7b82ba97..a07ee4548 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -71,11 +71,12 @@ pub async fn update_comment( let content = sanitize_html_opt(&content); let comment_id = data.comment_id; - let form = CommentUpdateForm::builder() - .content(content) - .language_id(data.language_id) - .updated(Some(Some(naive_now()))) - .build(); + let form = CommentUpdateForm { + content, + language_id: data.language_id, + updated: Some(Some(naive_now())), + ..Default::default() + }; let updated_comment = Comment::update(&mut context.pool(), comment_id, &form) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; @@ -104,7 +105,6 @@ pub async fn update_comment( &context, updated_comment.id, Some(local_user_view), - data.form_id.clone(), recipient_ids, ) .await?, diff --git a/crates/api_crud/src/community/delete.rs b/crates/api_crud/src/community/delete.rs index e23b1f404..9c8db512d 100644 --- a/crates/api_crud/src/community/delete.rs +++ b/crates/api_crud/src/community/delete.rs @@ -35,9 +35,10 @@ pub async fn delete_community( let community = Community::update( &mut context.pool(), community_id, - &CommunityUpdateForm::builder() - .deleted(Some(deleted)) - .build(), + &CommunityUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?; diff --git a/crates/api_crud/src/community/list.rs b/crates/api_crud/src/community/list.rs index c8ce9e58c..1f620dd9c 100644 --- a/crates/api_crud/src/community/list.rs +++ b/crates/api_crud/src/community/list.rs @@ -15,13 +15,16 @@ pub async fn list_communities( ) -> Result, LemmyError> { let local_user_view = local_user_view_from_jwt_opt(data.auth.as_ref(), &context).await; let local_site = LocalSite::read(&mut context.pool()).await?; - let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok()); + let is_admin = local_user_view + .as_ref() + .map(|luv| is_admin(luv).is_ok()) + .unwrap_or_default(); check_private_instance(&local_user_view, &local_site)?; let sort = data.sort; let listing_type = data.type_; - let show_nsfw = data.show_nsfw; + let show_nsfw = data.show_nsfw.unwrap_or_default(); let page = data.page; let limit = data.limit; let local_user = local_user_view.map(|l| l.local_user); diff --git a/crates/api_crud/src/community/remove.rs b/crates/api_crud/src/community/remove.rs index b79b2a666..f0bee639d 100644 --- a/crates/api_crud/src/community/remove.rs +++ b/crates/api_crud/src/community/remove.rs @@ -35,9 +35,10 @@ pub async fn remove_community( let community = Community::update( &mut context.pool(), community_id, - &CommunityUpdateForm::builder() - .removed(Some(removed)) - .build(), + &CommunityUpdateForm { + removed: Some(removed), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdateCommunity)?; diff --git a/crates/api_crud/src/community/update.rs b/crates/api_crud/src/community/update.rs index baa4e1bdb..cf53ff891 100644 --- a/crates/api_crud/src/community/update.rs +++ b/crates/api_crud/src/community/update.rs @@ -65,15 +65,16 @@ pub async fn update_community( CommunityLanguage::update(&mut context.pool(), languages, community_id).await?; } - let community_form = CommunityUpdateForm::builder() - .title(title) - .description(description) - .icon(icon) - .banner(banner) - .nsfw(data.nsfw) - .posting_restricted_to_mods(data.posting_restricted_to_mods) - .updated(Some(Some(naive_now()))) - .build(); + let community_form = CommunityUpdateForm { + title, + description, + icon, + banner, + nsfw: data.nsfw, + posting_restricted_to_mods: data.posting_restricted_to_mods, + updated: Some(Some(naive_now())), + ..Default::default() + }; let community_id = data.community_id; let community = Community::update(&mut context.pool(), community_id, &community_form) diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index dd88204a9..07e2cc27b 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -148,7 +148,10 @@ pub async fn create_post( let updated_post = Post::update( &mut context.pool(), inserted_post_id, - &PostUpdateForm::builder().ap_id(Some(apub_id)).build(), + &PostUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntCreatePost)?; diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs index 0d5eea886..79c8af0f0 100644 --- a/crates/api_crud/src/post/delete.rs +++ b/crates/api_crud/src/post/delete.rs @@ -45,9 +45,10 @@ pub async fn delete_post( let post = Post::update( &mut context.pool(), data.post_id, - &PostUpdateForm::builder() - .deleted(Some(data.deleted)) - .build(), + &PostUpdateForm { + deleted: Some(data.deleted), + ..Default::default() + }, ) .await?; diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index efa0c87b8..d37b1a582 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -52,14 +52,9 @@ pub async fn get_post( .await .is_ok(); - let post_view = PostView::read( - &mut context.pool(), - post_id, - person_id, - Some(is_mod_or_admin), - ) - .await - .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; + let post_view = PostView::read(&mut context.pool(), post_id, person_id, is_mod_or_admin) + .await + .with_lemmy_type(LemmyErrorType::CouldntFindPost)?; // Mark the post as read let post_id = post_view.post.id; @@ -72,7 +67,7 @@ pub async fn get_post( &mut context.pool(), community_id, person_id, - Some(is_mod_or_admin), + is_mod_or_admin, ) .await .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?; diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs index 4a87eb784..2fbd6ccff 100644 --- a/crates/api_crud/src/post/remove.rs +++ b/crates/api_crud/src/post/remove.rs @@ -11,8 +11,9 @@ use lemmy_db_schema::{ source::{ moderator::{ModRemovePost, ModRemovePostForm}, post::{Post, PostUpdateForm}, + post_report::PostReport, }, - traits::Crud, + traits::{Crud, Reportable}, }; use lemmy_utils::error::LemmyError; @@ -47,10 +48,16 @@ pub async fn remove_post( let post = Post::update( &mut context.pool(), post_id, - &PostUpdateForm::builder().removed(Some(removed)).build(), + &PostUpdateForm { + removed: Some(removed), + ..Default::default() + }, ) .await?; + PostReport::resolve_all_for_object(&mut context.pool(), post_id, local_user_view.person.id) + .await?; + // Mod tables let form = ModRemovePostForm { mod_person_id: local_user_view.person.id, diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index c831c88f1..a0f56aeb9 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -93,18 +93,19 @@ pub async fn update_post( ) .await?; - let post_form = PostUpdateForm::builder() - .name(name) - .url(url) - .body(body) - .nsfw(data.nsfw) - .embed_title(embed_title) - .embed_description(embed_description) - .embed_video_url(embed_video_url) - .language_id(data.language_id) - .thumbnail_url(Some(thumbnail_url)) - .updated(Some(Some(naive_now()))) - .build(); + let post_form = PostUpdateForm { + name, + url, + body, + nsfw: data.nsfw, + embed_title, + embed_description, + embed_video_url, + language_id: data.language_id, + thumbnail_url: Some(thumbnail_url), + updated: Some(Some(naive_now())), + ..Default::default() + }; let post_id = data.post_id; let updated_post = Post::update(&mut context.pool(), post_id, &post_form) diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index b9ac916f3..f5e4b15ab 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -67,9 +67,10 @@ pub async fn create_private_message( PrivateMessage::update( &mut context.pool(), inserted_private_message.id, - &PrivateMessageUpdateForm::builder() - .ap_id(Some(apub_id)) - .build(), + &PrivateMessageUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?; diff --git a/crates/api_crud/src/private_message/delete.rs b/crates/api_crud/src/private_message/delete.rs index 7657a7ff7..2a50dc0a2 100644 --- a/crates/api_crud/src/private_message/delete.rs +++ b/crates/api_crud/src/private_message/delete.rs @@ -33,9 +33,10 @@ pub async fn delete_private_message( let private_message = PrivateMessage::update( &mut context.pool(), private_message_id, - &PrivateMessageUpdateForm::builder() - .deleted(Some(deleted)) - .build(), + &PrivateMessageUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?; diff --git a/crates/api_crud/src/private_message/read.rs b/crates/api_crud/src/private_message/read.rs index ec4f5c102..0d3ba8620 100644 --- a/crates/api_crud/src/private_message/read.rs +++ b/crates/api_crud/src/private_message/read.rs @@ -17,11 +17,13 @@ pub async fn get_private_message( let page = data.page; let limit = data.limit; - let unread_only = data.unread_only; + let unread_only = data.unread_only.unwrap_or_default(); + let creator_id = data.creator_id; let mut messages = PrivateMessageQuery { page, limit, unread_only, + creator_id, } .list(&mut context.pool(), person_id) .await?; diff --git a/crates/api_crud/src/private_message/update.rs b/crates/api_crud/src/private_message/update.rs index eb24d7c12..d9e53776d 100644 --- a/crates/api_crud/src/private_message/update.rs +++ b/crates/api_crud/src/private_message/update.rs @@ -44,10 +44,11 @@ pub async fn update_private_message( PrivateMessage::update( &mut context.pool(), private_message_id, - &PrivateMessageUpdateForm::builder() - .content(Some(content)) - .updated(Some(Some(naive_now()))) - .build(), + &PrivateMessageUpdateForm { + content: Some(content), + updated: Some(Some(naive_now())), + ..Default::default() + }, ) .await .with_lemmy_type(LemmyErrorType::CouldntUpdatePrivateMessage)?; diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index 59a57ff8f..38d6111ce 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -60,18 +60,19 @@ pub async fn create_site( let sidebar = sanitize_html_opt(&data.sidebar); let description = sanitize_html_opt(&data.description); - let site_form = SiteUpdateForm::builder() - .name(Some(name)) - .sidebar(diesel_option_overwrite(sidebar)) - .description(diesel_option_overwrite(description)) - .icon(diesel_option_overwrite_to_url(&data.icon)?) - .banner(diesel_option_overwrite_to_url(&data.banner)?) - .actor_id(Some(actor_id)) - .last_refreshed_at(Some(naive_now())) - .inbox_url(inbox_url) - .private_key(Some(Some(keypair.private_key))) - .public_key(Some(keypair.public_key)) - .build(); + let site_form = SiteUpdateForm { + name: Some(name), + sidebar: diesel_option_overwrite(sidebar), + description: diesel_option_overwrite(description), + icon: diesel_option_overwrite_to_url(&data.icon)?, + banner: diesel_option_overwrite_to_url(&data.banner)?, + actor_id: Some(actor_id), + last_refreshed_at: Some(naive_now()), + inbox_url, + private_key: Some(Some(keypair.private_key)), + public_key: Some(keypair.public_key), + ..Default::default() + }; let site_id = local_site.site_id; @@ -81,45 +82,47 @@ pub async fn create_site( let default_theme = sanitize_html_opt(&data.default_theme); let legal_information = sanitize_html_opt(&data.legal_information); - let local_site_form = LocalSiteUpdateForm::builder() + let local_site_form = LocalSiteUpdateForm { // Set the site setup to true - .site_setup(Some(true)) - .enable_downvotes(data.enable_downvotes) - .registration_mode(data.registration_mode) - .enable_nsfw(data.enable_nsfw) - .community_creation_admin_only(data.community_creation_admin_only) - .require_email_verification(data.require_email_verification) - .application_question(diesel_option_overwrite(application_question)) - .private_instance(data.private_instance) - .default_theme(default_theme) - .default_post_listing_type(data.default_post_listing_type) - .legal_information(diesel_option_overwrite(legal_information)) - .application_email_admins(data.application_email_admins) - .hide_modlog_mod_names(data.hide_modlog_mod_names) - .updated(Some(Some(naive_now()))) - .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone())) - .actor_name_max_length(data.actor_name_max_length) - .federation_enabled(data.federation_enabled) - .captcha_enabled(data.captcha_enabled) - .captcha_difficulty(data.captcha_difficulty.clone()) - .build(); + site_setup: Some(true), + enable_downvotes: data.enable_downvotes, + registration_mode: data.registration_mode, + enable_nsfw: data.enable_nsfw, + community_creation_admin_only: data.community_creation_admin_only, + require_email_verification: data.require_email_verification, + application_question: diesel_option_overwrite(application_question), + private_instance: data.private_instance, + default_theme, + default_post_listing_type: data.default_post_listing_type, + legal_information: diesel_option_overwrite(legal_information), + application_email_admins: data.application_email_admins, + hide_modlog_mod_names: data.hide_modlog_mod_names, + updated: Some(Some(naive_now())), + slur_filter_regex: diesel_option_overwrite(data.slur_filter_regex.clone()), + actor_name_max_length: data.actor_name_max_length, + federation_enabled: data.federation_enabled, + captcha_enabled: data.captcha_enabled, + captcha_difficulty: data.captcha_difficulty.clone(), + ..Default::default() + }; LocalSite::update(&mut context.pool(), &local_site_form).await?; - let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder() - .message(data.rate_limit_message) - .message_per_second(data.rate_limit_message_per_second) - .post(data.rate_limit_post) - .post_per_second(data.rate_limit_post_per_second) - .register(data.rate_limit_register) - .register_per_second(data.rate_limit_register_per_second) - .image(data.rate_limit_image) - .image_per_second(data.rate_limit_image_per_second) - .comment(data.rate_limit_comment) - .comment_per_second(data.rate_limit_comment_per_second) - .search(data.rate_limit_search) - .search_per_second(data.rate_limit_search_per_second) - .build(); + let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm { + message: data.rate_limit_message, + message_per_second: data.rate_limit_message_per_second, + post: data.rate_limit_post, + post_per_second: data.rate_limit_post_per_second, + register: data.rate_limit_register, + register_per_second: data.rate_limit_register_per_second, + image: data.rate_limit_image, + image_per_second: data.rate_limit_image_per_second, + comment: data.rate_limit_comment, + comment_per_second: data.rate_limit_comment_per_second, + search: data.rate_limit_search, + search_per_second: data.rate_limit_search_per_second, + ..Default::default() + }; LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form).await?; @@ -144,7 +147,7 @@ pub async fn create_site( fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) -> LemmyResult<()> { // Make sure the site hasn't already been set up... if local_site.site_setup { - return Err(LemmyErrorType::SiteAlreadyExists)?; + Err(LemmyErrorType::SiteAlreadyExists)?; }; // Check that the slur regex compiles, and returns the regex if valid... diff --git a/crates/api_crud/src/site/update.rs b/crates/api_crud/src/site/update.rs index f560c7295..6148d546e 100644 --- a/crates/api_crud/src/site/update.rs +++ b/crates/api_crud/src/site/update.rs @@ -63,14 +63,15 @@ pub async fn update_site( let sidebar = sanitize_html_opt(&data.sidebar); let description = sanitize_html_opt(&data.description); - let site_form = SiteUpdateForm::builder() - .name(name) - .sidebar(diesel_option_overwrite(sidebar)) - .description(diesel_option_overwrite(description)) - .icon(diesel_option_overwrite_to_url(&data.icon)?) - .banner(diesel_option_overwrite_to_url(&data.banner)?) - .updated(Some(Some(naive_now()))) - .build(); + let site_form = SiteUpdateForm { + name, + sidebar: diesel_option_overwrite(sidebar), + description: diesel_option_overwrite(description), + icon: diesel_option_overwrite_to_url(&data.icon)?, + banner: diesel_option_overwrite_to_url(&data.banner)?, + updated: Some(Some(naive_now())), + ..Default::default() + }; Site::update(&mut context.pool(), site.id, &site_form) .await @@ -82,46 +83,48 @@ pub async fn update_site( let default_theme = sanitize_html_opt(&data.default_theme); let legal_information = sanitize_html_opt(&data.legal_information); - let local_site_form = LocalSiteUpdateForm::builder() - .enable_downvotes(data.enable_downvotes) - .registration_mode(data.registration_mode) - .enable_nsfw(data.enable_nsfw) - .community_creation_admin_only(data.community_creation_admin_only) - .require_email_verification(data.require_email_verification) - .application_question(diesel_option_overwrite(application_question)) - .private_instance(data.private_instance) - .default_theme(default_theme) - .default_post_listing_type(data.default_post_listing_type) - .legal_information(diesel_option_overwrite(legal_information)) - .application_email_admins(data.application_email_admins) - .hide_modlog_mod_names(data.hide_modlog_mod_names) - .updated(Some(Some(naive_now()))) - .slur_filter_regex(diesel_option_overwrite(data.slur_filter_regex.clone())) - .actor_name_max_length(data.actor_name_max_length) - .federation_enabled(data.federation_enabled) - .captcha_enabled(data.captcha_enabled) - .captcha_difficulty(data.captcha_difficulty.clone()) - .reports_email_admins(data.reports_email_admins) - .build(); + let local_site_form = LocalSiteUpdateForm { + enable_downvotes: data.enable_downvotes, + registration_mode: data.registration_mode, + enable_nsfw: data.enable_nsfw, + community_creation_admin_only: data.community_creation_admin_only, + require_email_verification: data.require_email_verification, + application_question: diesel_option_overwrite(application_question), + private_instance: data.private_instance, + default_theme, + default_post_listing_type: data.default_post_listing_type, + legal_information: diesel_option_overwrite(legal_information), + application_email_admins: data.application_email_admins, + hide_modlog_mod_names: data.hide_modlog_mod_names, + updated: Some(Some(naive_now())), + slur_filter_regex: diesel_option_overwrite(data.slur_filter_regex.clone()), + actor_name_max_length: data.actor_name_max_length, + federation_enabled: data.federation_enabled, + captcha_enabled: data.captcha_enabled, + captcha_difficulty: data.captcha_difficulty.clone(), + reports_email_admins: data.reports_email_admins, + ..Default::default() + }; let update_local_site = LocalSite::update(&mut context.pool(), &local_site_form) .await .ok(); - let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm::builder() - .message(data.rate_limit_message) - .message_per_second(data.rate_limit_message_per_second) - .post(data.rate_limit_post) - .post_per_second(data.rate_limit_post_per_second) - .register(data.rate_limit_register) - .register_per_second(data.rate_limit_register_per_second) - .image(data.rate_limit_image) - .image_per_second(data.rate_limit_image_per_second) - .comment(data.rate_limit_comment) - .comment_per_second(data.rate_limit_comment_per_second) - .search(data.rate_limit_search) - .search_per_second(data.rate_limit_search_per_second) - .build(); + let local_site_rate_limit_form = LocalSiteRateLimitUpdateForm { + message: data.rate_limit_message, + message_per_second: data.rate_limit_message_per_second, + post: data.rate_limit_post, + post_per_second: data.rate_limit_post_per_second, + register: data.rate_limit_register, + register_per_second: data.rate_limit_register_per_second, + image: data.rate_limit_image, + image_per_second: data.rate_limit_image_per_second, + comment: data.rate_limit_comment, + comment_per_second: data.rate_limit_comment_per_second, + search: data.rate_limit_search, + search_per_second: data.rate_limit_search_per_second, + ..Default::default() + }; LocalSiteRateLimit::update(&mut context.pool(), &local_site_rate_limit_form) .await diff --git a/crates/apub/src/activities/block/block_user.rs b/crates/apub/src/activities/block/block_user.rs index 7fd5768fd..d133e8f75 100644 --- a/crates/apub/src/activities/block/block_user.rs +++ b/crates/apub/src/activities/block/block_user.rs @@ -158,10 +158,11 @@ impl ActivityHandler for BlockUser { let blocked_person = Person::update( &mut context.pool(), blocked_person.id, - &PersonUpdateForm::builder() - .banned(Some(true)) - .ban_expires(Some(expires)) - .build(), + &PersonUpdateForm { + banned: Some(true), + ban_expires: Some(expires), + ..Default::default() + }, ) .await?; if self.remove_data.unwrap_or(false) { diff --git a/crates/apub/src/activities/block/undo_block_user.rs b/crates/apub/src/activities/block/undo_block_user.rs index 43f1b235c..9238a6952 100644 --- a/crates/apub/src/activities/block/undo_block_user.rs +++ b/crates/apub/src/activities/block/undo_block_user.rs @@ -106,10 +106,11 @@ impl ActivityHandler for UndoBlockUser { let blocked_person = Person::update( &mut context.pool(), blocked_person.id, - &PersonUpdateForm::builder() - .banned(Some(false)) - .ban_expires(Some(expires)) - .build(), + &PersonUpdateForm { + banned: Some(false), + ban_expires: Some(expires), + ..Default::default() + }, ) .await?; diff --git a/crates/apub/src/activities/community/collection_add.rs b/crates/apub/src/activities/community/collection_add.rs index 9257d1ff3..49e84f593 100644 --- a/crates/apub/src/activities/community/collection_add.rs +++ b/crates/apub/src/activities/community/collection_add.rs @@ -162,9 +162,10 @@ impl ActivityHandler for CollectionAdd { let post = ObjectId::::from(self.object) .dereference(context) .await?; - let form = PostUpdateForm::builder() - .featured_community(Some(true)) - .build(); + let form = PostUpdateForm { + featured_community: Some(true), + ..Default::default() + }; Post::update(&mut context.pool(), post.id, &form).await?; } } diff --git a/crates/apub/src/activities/community/collection_remove.rs b/crates/apub/src/activities/community/collection_remove.rs index 933247dd1..72d58c114 100644 --- a/crates/apub/src/activities/community/collection_remove.rs +++ b/crates/apub/src/activities/community/collection_remove.rs @@ -150,9 +150,10 @@ impl ActivityHandler for CollectionRemove { let post = ObjectId::::from(self.object) .dereference(context) .await?; - let form = PostUpdateForm::builder() - .featured_community(Some(false)) - .build(); + let form = PostUpdateForm { + featured_community: Some(false), + ..Default::default() + }; Post::update(&mut context.pool(), post.id, &form).await?; } } diff --git a/crates/apub/src/activities/community/lock_page.rs b/crates/apub/src/activities/community/lock_page.rs index df919a21c..b6caef9dc 100644 --- a/crates/apub/src/activities/community/lock_page.rs +++ b/crates/apub/src/activities/community/lock_page.rs @@ -57,7 +57,10 @@ impl ActivityHandler for LockPage { } async fn receive(self, context: &Data) -> Result<(), Self::Error> { - let form = PostUpdateForm::builder().locked(Some(true)).build(); + let form = PostUpdateForm { + locked: Some(true), + ..Default::default() + }; let post = self.object.dereference(context).await?; Post::update(&mut context.pool(), post.id, &form).await?; Ok(()) @@ -94,7 +97,10 @@ impl ActivityHandler for UndoLockPage { } async fn receive(self, context: &Data) -> Result<(), Self::Error> { - let form = PostUpdateForm::builder().locked(Some(false)).build(); + let form = PostUpdateForm { + locked: Some(false), + ..Default::default() + }; let post = self.object.object.dereference(context).await?; Post::update(&mut context.pool(), post.id, &form).await?; Ok(()) diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index 06f7463ae..fa0a44aa3 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -12,6 +12,7 @@ use lemmy_api_common::{context::LemmyContext, utils::sanitize_html_opt}; use lemmy_db_schema::{ source::{ comment::{Comment, CommentUpdateForm}, + comment_report::CommentReport, community::{Community, CommunityUpdateForm}, moderator::{ ModRemoveComment, @@ -22,8 +23,9 @@ use lemmy_db_schema::{ ModRemovePostForm, }, post::{Post, PostUpdateForm}, + post_report::PostReport, }, - traits::Crud, + traits::{Crud, Reportable}, }; use lemmy_utils::error::{LemmyError, LemmyErrorType}; use url::Url; @@ -123,11 +125,15 @@ pub(in crate::activities) async fn receive_remove_action( Community::update( &mut context.pool(), community.id, - &CommunityUpdateForm::builder().removed(Some(true)).build(), + &CommunityUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await?; } DeletableObjects::Post(post) => { + PostReport::resolve_all_for_object(&mut context.pool(), post.id, actor.id).await?; let form = ModRemovePostForm { mod_person_id: actor.id, post_id: post.id, @@ -138,11 +144,15 @@ pub(in crate::activities) async fn receive_remove_action( Post::update( &mut context.pool(), post.id, - &PostUpdateForm::builder().removed(Some(true)).build(), + &PostUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await?; } DeletableObjects::Comment(comment) => { + CommentReport::resolve_all_for_object(&mut context.pool(), comment.id, actor.id).await?; let form = ModRemoveCommentForm { mod_person_id: actor.id, comment_id: comment.id, @@ -153,7 +163,10 @@ pub(in crate::activities) async fn receive_remove_action( Comment::update( &mut context.pool(), comment.id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await?; } diff --git a/crates/apub/src/activities/deletion/mod.rs b/crates/apub/src/activities/deletion/mod.rs index 83046cfd9..74112fb58 100644 --- a/crates/apub/src/activities/deletion/mod.rs +++ b/crates/apub/src/activities/deletion/mod.rs @@ -252,16 +252,17 @@ async fn receive_delete_action( if community.local { let mod_: Person = actor.dereference(context).await?.deref().clone(); let object = DeletableObjects::Community(community.clone()); - let c: Community = community.deref().deref().clone(); + let c: Community = community.deref().clone(); send_apub_delete_in_community(mod_, c, object, None, true, context).await?; } Community::update( &mut context.pool(), community.id, - &CommunityUpdateForm::builder() - .deleted(Some(deleted)) - .build(), + &CommunityUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await?; } @@ -270,7 +271,10 @@ async fn receive_delete_action( Post::update( &mut context.pool(), post.id, - &PostUpdateForm::builder().deleted(Some(deleted)).build(), + &PostUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await?; } @@ -280,7 +284,10 @@ async fn receive_delete_action( Comment::update( &mut context.pool(), comment.id, - &CommentUpdateForm::builder().deleted(Some(deleted)).build(), + &CommentUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await?; } @@ -289,9 +296,10 @@ async fn receive_delete_action( PrivateMessage::update( &mut context.pool(), pm.id, - &PrivateMessageUpdateForm::builder() - .deleted(Some(deleted)) - .build(), + &PrivateMessageUpdateForm { + deleted: Some(deleted), + ..Default::default() + }, ) .await?; } diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index 541a7455f..4d7822042 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -113,7 +113,10 @@ impl UndoDelete { Community::update( &mut context.pool(), community.id, - &CommunityUpdateForm::builder().removed(Some(false)).build(), + &CommunityUpdateForm { + removed: Some(false), + ..Default::default() + }, ) .await?; } @@ -128,7 +131,10 @@ impl UndoDelete { Post::update( &mut context.pool(), post.id, - &PostUpdateForm::builder().removed(Some(false)).build(), + &PostUpdateForm { + removed: Some(false), + ..Default::default() + }, ) .await?; } @@ -143,7 +149,10 @@ impl UndoDelete { Comment::update( &mut context.pool(), comment.id, - &CommentUpdateForm::builder().removed(Some(false)).build(), + &CommentUpdateForm { + removed: Some(false), + ..Default::default() + }, ) .await?; } diff --git a/crates/apub/src/activities/mod.rs b/crates/apub/src/activities/mod.rs index 5641e322f..844745a4a 100644 --- a/crates/apub/src/activities/mod.rs +++ b/crates/apub/src/activities/mod.rs @@ -93,7 +93,9 @@ pub(crate) async fn verify_person_in_community( ) -> Result<(), LemmyError> { let person = person_id.dereference(context).await?; if person.banned { - return Err(LemmyErrorType::PersonIsBannedFromSite)?; + return Err(LemmyErrorType::PersonIsBannedFromSite( + person.actor_id.to_string(), + ))?; } let person_id = person.id; let community_id = community.id; @@ -139,7 +141,7 @@ pub(crate) async fn verify_mod_action( pub(crate) fn verify_is_public(to: &[Url], cc: &[Url]) -> Result<(), LemmyError> { if ![to, cc].iter().any(|set| set.contains(&public())) { - return Err(LemmyErrorType::ObjectIsNotPublic)?; + Err(LemmyErrorType::ObjectIsNotPublic)?; } Ok(()) } @@ -153,7 +155,7 @@ where { let b: ObjectId = b.into(); if a != &b { - return Err(LemmyErrorType::InvalidCommunity)?; + Err(LemmyErrorType::InvalidCommunity)?; } Ok(()) } diff --git a/crates/apub/src/api/list_comments.rs b/crates/apub/src/api/list_comments.rs index f07ce3dad..5d7aa387b 100644 --- a/crates/apub/src/api/list_comments.rs +++ b/crates/apub/src/api/list_comments.rs @@ -34,7 +34,14 @@ pub async fn list_comments( }; let sort = data.sort; let max_depth = data.max_depth; - let saved_only = data.saved_only; + let saved_only = data.saved_only.unwrap_or_default(); + + let liked_only = data.liked_only.unwrap_or_default(); + let disliked_only = data.disliked_only.unwrap_or_default(); + if liked_only && disliked_only { + return Err(LemmyError::from(LemmyErrorType::ContradictingFilters)); + } + let page = data.page; let limit = data.limit; let parent_id = data.parent_id; @@ -59,6 +66,8 @@ pub async fn list_comments( sort, max_depth, saved_only, + liked_only, + disliked_only, community_id, parent_path: parent_path_cloned, post_id, diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index 2635e149e..c43e1381e 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -34,9 +34,15 @@ pub async fn list_posts( } else { data.community_id }; - let saved_only = data.saved_only; + let saved_only = data.saved_only.unwrap_or_default(); - let moderator_view = data.moderator_view; + let liked_only = data.liked_only.unwrap_or_default(); + let disliked_only = data.disliked_only.unwrap_or_default(); + if liked_only && disliked_only { + return Err(LemmyError::from(LemmyErrorType::ContradictingFilters)); + } + + let moderator_view = data.moderator_view.unwrap_or_default(); let listing_type = Some(listing_type_with_default( data.type_, @@ -50,6 +56,8 @@ pub async fn list_posts( sort, community_id, saved_only, + liked_only, + disliked_only, moderator_view, page, limit, diff --git a/crates/apub/src/api/read_community.rs b/crates/apub/src/api/read_community.rs index 1bdfb88a0..9f6e43571 100644 --- a/crates/apub/src/api/read_community.rs +++ b/crates/apub/src/api/read_community.rs @@ -54,7 +54,7 @@ pub async fn get_community( &mut context.pool(), community_id, person_id, - Some(is_mod_or_admin), + is_mod_or_admin, ) .await .with_lemmy_type(LemmyErrorType::CouldntFindCommunity)?; diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index 5d3c73c30..23d6457af 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -50,11 +50,11 @@ pub async fn read_person( let sort = data.sort; let page = data.page; let limit = data.limit; - let saved_only = data.saved_only; + let saved_only = data.saved_only.unwrap_or_default(); let community_id = data.community_id; // If its saved only, you don't care what creator it was // Or, if its not saved, then you only want it for that specific creator - let creator_id = if !saved_only.unwrap_or(false) { + let creator_id = if !saved_only { Some(person_details_id) } else { None @@ -65,7 +65,7 @@ pub async fn read_person( saved_only, local_user: local_user_view.as_ref(), community_id, - is_profile_view: Some(true), + is_profile_view: true, page, limit, creator_id, @@ -75,14 +75,13 @@ pub async fn read_person( .await?; let comments = CommentQuery { - local_user: (local_user_view.as_ref()), - sort: (sort.map(post_to_comment_sort_type)), - saved_only: (saved_only), - show_deleted_and_removed: (Some(false)), - community_id: (community_id), - is_profile_view: Some(true), - page: (page), - limit: (limit), + local_user: local_user_view.as_ref(), + sort: sort.map(post_to_comment_sort_type), + saved_only, + community_id, + is_profile_view: true, + page, + limit, creator_id, ..Default::default() } diff --git a/crates/apub/src/api/resolve_object.rs b/crates/apub/src/api/resolve_object.rs index 898cc8d51..f5a703c99 100644 --- a/crates/apub/src/api/resolve_object.rs +++ b/crates/apub/src/api/resolve_object.rs @@ -58,11 +58,11 @@ async fn convert_response( } Community(c) => { removed_or_deleted = c.deleted || c.removed; - res.community = Some(CommunityView::read(pool, c.id, user_id, None).await?) + res.community = Some(CommunityView::read(pool, c.id, user_id, false).await?) } Post(p) => { removed_or_deleted = p.deleted || p.removed; - res.post = Some(PostView::read(pool, p.id, user_id, None).await?) + res.post = Some(PostView::read(pool, p.id, user_id, false).await?) } Comment(c) => { removed_or_deleted = c.deleted || c.removed; diff --git a/crates/apub/src/api/search.rs b/crates/apub/src/api/search.rs index aaea69e07..55d86b081 100644 --- a/crates/apub/src/api/search.rs +++ b/crates/apub/src/api/search.rs @@ -25,7 +25,10 @@ pub async fn search( check_private_instance(&local_user_view, &local_site)?; - let is_admin = local_user_view.as_ref().map(|luv| is_admin(luv).is_ok()); + let is_admin = local_user_view + .as_ref() + .map(|luv| is_admin(luv).is_ok()) + .unwrap_or_default(); let mut posts = Vec::new(); let mut comments = Vec::new(); diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index d9562ca27..8b94cca9d 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -78,7 +78,7 @@ fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result .map(|l| l.federation_enabled) .unwrap_or(true) { - return Err(LemmyErrorType::FederationDisabled)?; + Err(LemmyErrorType::FederationDisabled)?; } if local_site_data @@ -86,7 +86,7 @@ fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result .iter() .any(|i| domain.eq(&i.domain)) { - return Err(LemmyErrorType::DomainBlocked(domain))?; + Err(LemmyErrorType::DomainBlocked(domain.clone()))?; } // Only check this if there are instances in the allowlist @@ -96,7 +96,7 @@ fn check_apub_id_valid(apub_id: &Url, local_site_data: &LocalSiteData) -> Result .iter() .any(|i| domain.eq(&i.domain)) { - return Err(LemmyErrorType::DomainNotInAllowList(domain))?; + Err(LemmyErrorType::DomainNotInAllowList(domain))?; } Ok(()) diff --git a/crates/apub/src/objects/comment.rs b/crates/apub/src/objects/comment.rs index 3b05ed394..1b7724431 100644 --- a/crates/apub/src/objects/comment.rs +++ b/crates/apub/src/objects/comment.rs @@ -78,7 +78,10 @@ impl Object for ApubComment { #[tracing::instrument(skip_all)] async fn delete(self, context: &Data) -> Result<(), LemmyError> { if !self.deleted { - let form = CommentUpdateForm::builder().deleted(Some(true)).build(); + let form = CommentUpdateForm { + deleted: Some(true), + ..Default::default() + }; Comment::update(&mut context.pool(), self.id, &form).await?; } Ok(()) diff --git a/crates/apub/src/objects/community.rs b/crates/apub/src/objects/community.rs index 665d9db8c..8dba209d6 100644 --- a/crates/apub/src/objects/community.rs +++ b/crates/apub/src/objects/community.rs @@ -76,7 +76,10 @@ impl Object for ApubCommunity { #[tracing::instrument(skip_all)] async fn delete(self, context: &Data) -> Result<(), LemmyError> { - let form = CommunityUpdateForm::builder().deleted(Some(true)).build(); + let form = CommunityUpdateForm { + deleted: Some(true), + ..Default::default() + }; Community::update(&mut context.pool(), self.id, &form).await?; Ok(()) } diff --git a/crates/apub/src/objects/person.rs b/crates/apub/src/objects/person.rs index 1947c4d72..d17ad235b 100644 --- a/crates/apub/src/objects/person.rs +++ b/crates/apub/src/objects/person.rs @@ -81,7 +81,10 @@ impl Object for ApubPerson { #[tracing::instrument(skip_all)] async fn delete(self, context: &Data) -> Result<(), LemmyError> { - let form = PersonUpdateForm::builder().deleted(Some(true)).build(); + let form = PersonUpdateForm { + deleted: Some(true), + ..Default::default() + }; DbPerson::update(&mut context.pool(), self.id, &form).await?; Ok(()) } diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index f04e07ded..df3aefed2 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -99,7 +99,10 @@ impl Object for ApubPost { #[tracing::instrument(skip_all)] async fn delete(self, context: &Data) -> Result<(), LemmyError> { if !self.deleted { - let form = PostUpdateForm::builder().deleted(Some(true)).build(); + let form = PostUpdateForm { + deleted: Some(true), + ..Default::default() + }; Post::update(&mut context.pool(), self.id, &form).await?; } Ok(()) diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index a51cfe6b7..9a92b0b51 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -107,7 +107,9 @@ impl Object for ApubPrivateMessage { check_apub_id_valid_with_strictness(note.id.inner(), false, context).await?; let person = note.attributed_to.dereference(context).await?; if person.banned { - return Err(LemmyErrorType::PersonIsBannedFromSite)?; + return Err(LemmyErrorType::PersonIsBannedFromSite( + person.actor_id.to_string(), + ))?; } Ok(()) } diff --git a/crates/db_schema/src/aggregates/person_aggregates.rs b/crates/db_schema/src/aggregates/person_aggregates.rs index 2e71844fa..e6195de28 100644 --- a/crates/db_schema/src/aggregates/person_aggregates.rs +++ b/crates/db_schema/src/aggregates/person_aggregates.rs @@ -145,14 +145,20 @@ mod tests { Comment::update( pool, inserted_comment.id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); Comment::update( pool, inserted_child_comment.id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); diff --git a/crates/db_schema/src/aggregates/post_aggregates.rs b/crates/db_schema/src/aggregates/post_aggregates.rs index 020370825..7847f3946 100644 --- a/crates/db_schema/src/aggregates/post_aggregates.rs +++ b/crates/db_schema/src/aggregates/post_aggregates.rs @@ -235,7 +235,10 @@ mod tests { Comment::update( pool, inserted_comment.id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); @@ -246,7 +249,10 @@ mod tests { Comment::update( pool, inserted_comment.id, - &CommentUpdateForm::builder().removed(Some(false)).build(), + &CommentUpdateForm { + removed: Some(false), + ..Default::default() + }, ) .await .unwrap(); @@ -254,7 +260,10 @@ mod tests { Comment::update( pool, inserted_comment.id, - &CommentUpdateForm::builder().deleted(Some(true)).build(), + &CommentUpdateForm { + deleted: Some(true), + ..Default::default() + }, ) .await .unwrap(); @@ -265,7 +274,10 @@ mod tests { Comment::update( pool, inserted_comment.id, - &CommentUpdateForm::builder().removed(Some(true)).build(), + &CommentUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); diff --git a/crates/db_schema/src/aggregates/site_aggregates.rs b/crates/db_schema/src/aggregates/site_aggregates.rs index ea3da85ae..4fe57720a 100644 --- a/crates/db_schema/src/aggregates/site_aggregates.rs +++ b/crates/db_schema/src/aggregates/site_aggregates.rs @@ -160,7 +160,10 @@ mod tests { Community::update( pool, inserted_community.id, - &CommunityUpdateForm::builder().deleted(Some(true)).build(), + &CommunityUpdateForm { + deleted: Some(true), + ..Default::default() + }, ) .await .unwrap(); @@ -171,7 +174,10 @@ mod tests { Community::update( pool, inserted_community.id, - &CommunityUpdateForm::builder().deleted(Some(false)).build(), + &CommunityUpdateForm { + deleted: Some(false), + ..Default::default() + }, ) .await .unwrap(); @@ -179,7 +185,10 @@ mod tests { Community::update( pool, inserted_community.id, - &CommunityUpdateForm::builder().removed(Some(true)).build(), + &CommunityUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); @@ -190,7 +199,10 @@ mod tests { Community::update( pool, inserted_community.id, - &CommunityUpdateForm::builder().deleted(Some(true)).build(), + &CommunityUpdateForm { + deleted: Some(true), + ..Default::default() + }, ) .await .unwrap(); diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 88757cd02..cab033df3 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -372,9 +372,10 @@ mod tests { published: inserted_comment_saved.published, }; - let comment_update_form = CommentUpdateForm::builder() - .content(Some("A test comment".into())) - .build(); + let comment_update_form = CommentUpdateForm { + content: Some("A test comment".into()), + ..Default::default() + }; let updated_comment = Comment::update(pool, inserted_comment.id, &comment_update_form) .await diff --git a/crates/db_schema/src/impls/comment_report.rs b/crates/db_schema/src/impls/comment_report.rs index ff93915e1..19c12876f 100644 --- a/crates/db_schema/src/impls/comment_report.rs +++ b/crates/db_schema/src/impls/comment_report.rs @@ -1,6 +1,9 @@ use crate::{ - newtypes::{CommentReportId, PersonId}, - schema::comment_report::dsl::{comment_report, resolved, resolver_id, updated}, + newtypes::{CommentId, CommentReportId, PersonId}, + schema::comment_report::{ + comment_id, + dsl::{comment_report, resolved, resolver_id, updated}, + }, source::comment_report::{CommentReport, CommentReportForm}, traits::Reportable, utils::{get_conn, naive_now, DbPool}, @@ -17,6 +20,7 @@ use diesel_async::RunQueryDsl; impl Reportable for CommentReport { type Form = CommentReportForm; type IdType = CommentReportId; + type ObjectIdType = CommentId; /// creates a comment report and returns it /// /// * `conn` - the postgres connection @@ -53,6 +57,22 @@ impl Reportable for CommentReport { .await } + async fn resolve_all_for_object( + pool: &mut DbPool<'_>, + comment_id_: CommentId, + by_resolver_id: PersonId, + ) -> Result { + let conn = &mut get_conn(pool).await?; + update(comment_report.filter(comment_id.eq(comment_id_))) + .set(( + resolved.eq(true), + resolver_id.eq(by_resolver_id), + updated.eq(naive_now()), + )) + .execute(conn) + .await + } + /// unresolve a comment report /// /// * `conn` - the postgres connection diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 2d0fcfe57..bedb9820e 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -1,6 +1,6 @@ use crate::{ newtypes::{CommunityId, DbUrl, PersonId}, - schema::{community, instance}, + schema::{community, community_follower, instance}, source::{ actor_language::CommunityLanguage, community::{ @@ -19,7 +19,18 @@ use crate::{ utils::{functions::lower, get_conn, DbPool}, SubscribedType, }; -use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; +use diesel::{ + deserialize, + dsl, + dsl::insert_into, + pg::Pg, + result::Error, + sql_types, + ExpressionMethods, + NullableExpressionMethods, + QueryDsl, + Queryable, +}; use diesel_async::RunQueryDsl; #[async_trait] @@ -214,6 +225,21 @@ impl CommunityFollower { None => SubscribedType::NotSubscribed, } } + + pub fn select_subscribed_type() -> dsl::Nullable { + community_follower::pending.nullable() + } +} + +impl Queryable, Pg> for SubscribedType { + type Row = Option; + fn build(row: Self::Row) -> deserialize::Result { + Ok(match row { + Some(true) => SubscribedType::Pending, + Some(false) => SubscribedType::Subscribed, + None => SubscribedType::NotSubscribed, + }) + } } #[async_trait] @@ -449,9 +475,10 @@ mod tests { let read_community = Community::read(pool, inserted_community.id).await.unwrap(); - let update_community_form = CommunityUpdateForm::builder() - .title(Some("nada".to_owned())) - .build(); + let update_community_form = CommunityUpdateForm { + title: Some("nada".to_owned()), + ..Default::default() + }; let updated_community = Community::update(pool, inserted_community.id, &update_community_form) .await .unwrap(); diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 53f4a4df0..43bdf5c3b 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -253,9 +253,10 @@ mod tests { let read_person = Person::read(pool, inserted_person.id).await.unwrap(); - let update_person_form = PersonUpdateForm::builder() - .actor_id(Some(inserted_person.actor_id.clone())) - .build(); + let update_person_form = PersonUpdateForm { + actor_id: Some(inserted_person.actor_id.clone()), + ..Default::default() + }; let updated_person = Person::update(pool, inserted_person.id, &update_person_form) .await .unwrap(); diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index 60b8af2ce..a798ddcb0 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -453,9 +453,10 @@ mod tests { let read_post = Post::read(pool, inserted_post.id).await.unwrap(); - let new_post_update = PostUpdateForm::builder() - .name(Some("A test post".into())) - .build(); + let new_post_update = PostUpdateForm { + name: Some("A test post".into()), + ..Default::default() + }; let updated_post = Post::update(pool, inserted_post.id, &new_post_update) .await .unwrap(); diff --git a/crates/db_schema/src/impls/post_report.rs b/crates/db_schema/src/impls/post_report.rs index b839d62d5..face766db 100644 --- a/crates/db_schema/src/impls/post_report.rs +++ b/crates/db_schema/src/impls/post_report.rs @@ -1,6 +1,9 @@ use crate::{ - newtypes::{PersonId, PostReportId}, - schema::post_report::dsl::{post_report, resolved, resolver_id, updated}, + newtypes::{PersonId, PostId, PostReportId}, + schema::post_report::{ + dsl::{post_report, resolved, resolver_id, updated}, + post_id, + }, source::post_report::{PostReport, PostReportForm}, traits::Reportable, utils::{get_conn, naive_now, DbPool}, @@ -17,6 +20,7 @@ use diesel_async::RunQueryDsl; impl Reportable for PostReport { type Form = PostReportForm; type IdType = PostReportId; + type ObjectIdType = PostId; async fn report(pool: &mut DbPool<'_>, post_report_form: &PostReportForm) -> Result { let conn = &mut get_conn(pool).await?; @@ -42,6 +46,22 @@ impl Reportable for PostReport { .await } + async fn resolve_all_for_object( + pool: &mut DbPool<'_>, + post_id_: PostId, + by_resolver_id: PersonId, + ) -> Result { + let conn = &mut get_conn(pool).await?; + update(post_report.filter(post_id.eq(post_id_))) + .set(( + resolved.eq(true), + resolver_id.eq(by_resolver_id), + updated.eq(naive_now()), + )) + .execute(conn) + .await + } + async fn unresolve( pool: &mut DbPool<'_>, report_id: Self::IdType, @@ -58,3 +78,97 @@ impl Reportable for PostReport { .await } } + +#[cfg(test)] +mod tests { + #![allow(clippy::unwrap_used)] + #![allow(clippy::indexing_slicing)] + + use super::*; + use crate::{ + source::{ + community::{Community, CommunityInsertForm}, + instance::Instance, + person::{Person, PersonInsertForm}, + post::{Post, PostInsertForm}, + }, + traits::Crud, + utils::build_db_pool_for_tests, + }; + use serial_test::serial; + + async fn init(pool: &mut DbPool<'_>) -> (Person, PostReport) { + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) + .await + .unwrap(); + let person_form = PersonInsertForm::builder() + .name("jim".into()) + .public_key("pubkey".to_string()) + .instance_id(inserted_instance.id) + .build(); + let person = Person::create(pool, &person_form).await.unwrap(); + + let community_form = CommunityInsertForm::builder() + .name("test community_4".to_string()) + .title("nada".to_owned()) + .public_key("pubkey".to_string()) + .instance_id(inserted_instance.id) + .build(); + let community = Community::create(pool, &community_form).await.unwrap(); + + let form = PostInsertForm::builder() + .name("A test post".into()) + .creator_id(person.id) + .community_id(community.id) + .build(); + let post = Post::create(pool, &form).await.unwrap(); + + let report_form = PostReportForm { + post_id: post.id, + creator_id: person.id, + reason: "my reason".to_string(), + ..Default::default() + }; + let report = PostReport::report(pool, &report_form).await.unwrap(); + (person, report) + } + + #[tokio::test] + #[serial] + async fn test_resolve_post_report() { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + + let (person, report) = init(pool).await; + + let resolved_count = PostReport::resolve(pool, report.id, person.id) + .await + .unwrap(); + assert_eq!(resolved_count, 1); + + let unresolved_count = PostReport::unresolve(pool, report.id, person.id) + .await + .unwrap(); + assert_eq!(unresolved_count, 1); + + Person::delete(pool, person.id).await.unwrap(); + Post::delete(pool, report.post_id).await.unwrap(); + } + + #[tokio::test] + #[serial] + async fn test_resolve_all_post_reports() { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + + let (person, report) = init(pool).await; + + let resolved_count = PostReport::resolve_all_for_object(pool, report.post_id, person.id) + .await + .unwrap(); + assert_eq!(resolved_count, 1); + + Person::delete(pool, person.id).await.unwrap(); + Post::delete(pool, report.post_id).await.unwrap(); + } +} diff --git a/crates/db_schema/src/impls/private_message.rs b/crates/db_schema/src/impls/private_message.rs index d422f0d23..81a4b1850 100644 --- a/crates/db_schema/src/impls/private_message.rs +++ b/crates/db_schema/src/impls/private_message.rs @@ -142,9 +142,10 @@ mod tests { .await .unwrap(); - let private_message_update_form = PrivateMessageUpdateForm::builder() - .content(Some("A test private message".into())) - .build(); + let private_message_update_form = PrivateMessageUpdateForm { + content: Some("A test private message".into()), + ..Default::default() + }; let updated_private_message = PrivateMessage::update( pool, inserted_private_message.id, @@ -156,16 +157,20 @@ mod tests { let deleted_private_message = PrivateMessage::update( pool, inserted_private_message.id, - &PrivateMessageUpdateForm::builder() - .deleted(Some(true)) - .build(), + &PrivateMessageUpdateForm { + deleted: Some(true), + ..Default::default() + }, ) .await .unwrap(); let marked_read_private_message = PrivateMessage::update( pool, inserted_private_message.id, - &PrivateMessageUpdateForm::builder().read(Some(true)).build(), + &PrivateMessageUpdateForm { + read: Some(true), + ..Default::default() + }, ) .await .unwrap(); diff --git a/crates/db_schema/src/impls/private_message_report.rs b/crates/db_schema/src/impls/private_message_report.rs index ca2187960..c20783db0 100644 --- a/crates/db_schema/src/impls/private_message_report.rs +++ b/crates/db_schema/src/impls/private_message_report.rs @@ -1,5 +1,5 @@ use crate::{ - newtypes::{PersonId, PrivateMessageReportId}, + newtypes::{PersonId, PrivateMessageId, PrivateMessageReportId}, schema::private_message_report::dsl::{private_message_report, resolved, resolver_id, updated}, source::private_message_report::{PrivateMessageReport, PrivateMessageReportForm}, traits::Reportable, @@ -17,6 +17,7 @@ use diesel_async::RunQueryDsl; impl Reportable for PrivateMessageReport { type Form = PrivateMessageReportForm; type IdType = PrivateMessageReportId; + type ObjectIdType = PrivateMessageId; async fn report( pool: &mut DbPool<'_>, @@ -45,6 +46,15 @@ impl Reportable for PrivateMessageReport { .await } + // TODO: this is unused because private message doesnt have remove handler + async fn resolve_all_for_object( + _pool: &mut DbPool<'_>, + _pm_id_: PrivateMessageId, + _by_resolver_id: PersonId, + ) -> Result { + unimplemented!() + } + async fn unresolve( pool: &mut DbPool<'_>, report_id: Self::IdType, diff --git a/crates/db_schema/src/source/comment.rs b/crates/db_schema/src/source/comment.rs index ecf745ee9..f76e2fba7 100644 --- a/crates/db_schema/src/source/comment.rs +++ b/crates/db_schema/src/source/comment.rs @@ -66,8 +66,7 @@ pub struct CommentInsertForm { pub language_id: Option, } -#[derive(Debug, Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = comment))] pub struct CommentUpdateForm { diff --git a/crates/db_schema/src/source/community.rs b/crates/db_schema/src/source/community.rs index 64b30b2a8..5d56c36a5 100644 --- a/crates/db_schema/src/source/community.rs +++ b/crates/db_schema/src/source/community.rs @@ -97,8 +97,7 @@ pub struct CommunityInsertForm { pub instance_id: InstanceId, } -#[derive(Debug, Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = community))] pub struct CommunityUpdateForm { diff --git a/crates/db_schema/src/source/local_site.rs b/crates/db_schema/src/source/local_site.rs index be93717a9..a57bf503c 100644 --- a/crates/db_schema/src/source/local_site.rs +++ b/crates/db_schema/src/source/local_site.rs @@ -89,8 +89,7 @@ pub struct LocalSiteInsertForm { pub reports_email_admins: Option, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = local_site))] pub struct LocalSiteUpdateForm { diff --git a/crates/db_schema/src/source/local_site_rate_limit.rs b/crates/db_schema/src/source/local_site_rate_limit.rs index 9d3e3a250..ab14bfd83 100644 --- a/crates/db_schema/src/source/local_site_rate_limit.rs +++ b/crates/db_schema/src/source/local_site_rate_limit.rs @@ -57,8 +57,7 @@ pub struct LocalSiteRateLimitInsertForm { pub search_per_second: Option, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = local_site_rate_limit))] pub struct LocalSiteRateLimitUpdateForm { diff --git a/crates/db_schema/src/source/local_user.rs b/crates/db_schema/src/source/local_user.rs index 0d8db6693..4e668bddf 100644 --- a/crates/db_schema/src/source/local_user.rs +++ b/crates/db_schema/src/source/local_user.rs @@ -90,8 +90,7 @@ pub struct LocalUserInsertForm { pub infinite_scroll_enabled: Option, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = local_user))] pub struct LocalUserUpdateForm { diff --git a/crates/db_schema/src/source/person.rs b/crates/db_schema/src/source/person.rs index 82d6f61a2..7772bb118 100644 --- a/crates/db_schema/src/source/person.rs +++ b/crates/db_schema/src/source/person.rs @@ -89,10 +89,9 @@ pub struct PersonInsertForm { pub ban_expires: Option, } -#[derive(Clone, TypedBuilder)] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = person))] -#[builder(field_defaults(default))] pub struct PersonUpdateForm { pub display_name: Option>, pub avatar: Option>, diff --git a/crates/db_schema/src/source/post.rs b/crates/db_schema/src/source/post.rs index 27eac6d98..de56f1187 100644 --- a/crates/db_schema/src/source/post.rs +++ b/crates/db_schema/src/source/post.rs @@ -85,8 +85,7 @@ pub struct PostInsertForm { pub featured_local: Option, } -#[derive(Debug, Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Debug, Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = post))] pub struct PostUpdateForm { diff --git a/crates/db_schema/src/source/post_report.rs b/crates/db_schema/src/source/post_report.rs index 0d09b5e9d..74e418670 100644 --- a/crates/db_schema/src/source/post_report.rs +++ b/crates/db_schema/src/source/post_report.rs @@ -30,7 +30,7 @@ pub struct PostReport { pub updated: Option, } -#[derive(Clone)] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = post_report))] pub struct PostReportForm { diff --git a/crates/db_schema/src/source/private_message.rs b/crates/db_schema/src/source/private_message.rs index 0ceaf762f..bd8c73e30 100644 --- a/crates/db_schema/src/source/private_message.rs +++ b/crates/db_schema/src/source/private_message.rs @@ -49,8 +49,7 @@ pub struct PrivateMessageInsertForm { pub local: Option, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = private_message))] pub struct PrivateMessageUpdateForm { diff --git a/crates/db_schema/src/source/site.rs b/crates/db_schema/src/source/site.rs index 12b30c584..e45ece706 100644 --- a/crates/db_schema/src/source/site.rs +++ b/crates/db_schema/src/source/site.rs @@ -59,8 +59,7 @@ pub struct SiteInsertForm { pub instance_id: InstanceId, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, Default)] #[cfg_attr(feature = "full", derive(AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = site))] pub struct SiteUpdateForm { diff --git a/crates/db_schema/src/traits.rs b/crates/db_schema/src/traits.rs index 07f0b07e2..cb128339b 100644 --- a/crates/db_schema/src/traits.rs +++ b/crates/db_schema/src/traits.rs @@ -155,6 +155,7 @@ pub trait Readable { pub trait Reportable { type Form; type IdType; + type ObjectIdType; async fn report(pool: &mut DbPool<'_>, form: &Self::Form) -> Result where Self: Sized; @@ -163,6 +164,13 @@ pub trait Reportable { report_id: Self::IdType, resolver_id: PersonId, ) -> Result + where + Self: Sized; + async fn resolve_all_for_object( + pool: &mut DbPool<'_>, + comment_id_: Self::ObjectIdType, + by_resolver_id: PersonId, + ) -> Result where Self: Sized; async fn unresolve( diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index a92b38063..98ff555b7 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -28,7 +28,7 @@ use lemmy_db_schema::{ source::{ comment::Comment, comment_report::CommentReport, - community::{Community, CommunityPersonBan}, + community::Community, person::Person, post::Post, }, @@ -71,7 +71,7 @@ fn queries<'a>() -> Queries< person::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - community_person_ban::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), comment_like::score.nullable(), aliases::person2.fields(person::all_columns).nullable(), ); @@ -113,7 +113,7 @@ fn queries<'a>() -> Queries< query = query.filter(post::community_id.eq(community_id)); } - if options.unresolved_only.unwrap_or(false) { + if options.unresolved_only { query = query.filter(comment_report::resolved.eq(false)); } @@ -206,7 +206,7 @@ pub struct CommentReportQuery { pub community_id: Option, pub page: Option, pub limit: Option, - pub unresolved_only: Option, + pub unresolved_only: bool, } impl CommentReportQuery { @@ -228,7 +228,7 @@ impl JoinView for CommentReportView { Person, Person, CommentAggregates, - Option, + bool, Option, Option, ); @@ -242,7 +242,7 @@ impl JoinView for CommentReportView { creator: a.4, comment_creator: a.5, counts: a.6, - creator_banned_from_community: a.7.is_some(), + creator_banned_from_community: a.7, my_vote: a.8, resolver: a.9, } @@ -569,7 +569,7 @@ mod tests { // Do a batch read of timmys reports // It should only show saras, which is unresolved let reports_after_resolve = CommentReportQuery { - unresolved_only: (Some(true)), + unresolved_only: (true), ..Default::default() } .list(pool, &inserted_timmy) diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 26787cceb..be7e043a2 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -29,16 +29,16 @@ use lemmy_db_schema::{ post, }, source::{ - comment::{Comment, CommentSaved}, - community::{Community, CommunityFollower, CommunityPersonBan}, + comment::Comment, + community::{Community, CommunityFollower}, person::Person, - person_block::PersonBlock, post::Post, }, traits::JoinView, utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, CommentSortType, ListingType, + SubscribedType, }; type CommentViewTuple = ( @@ -47,10 +47,10 @@ type CommentViewTuple = ( Post, Community, CommentAggregates, - Option, - Option, - Option, - Option, + bool, + SubscribedType, + bool, + bool, Option, ); @@ -109,10 +109,10 @@ fn queries<'a>() -> Queries< post::all_columns, community::all_columns, comment_aggregates::all_columns, - community_person_ban::all_columns.nullable(), - community_follower::all_columns.nullable(), - comment_saved::all_columns.nullable(), - person_block::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), + CommunityFollower::select_subscribed_type(), + comment_saved::id.nullable().is_not_null(), + person_block::id.nullable().is_not_null(), comment_like::score.nullable(), ); @@ -171,9 +171,7 @@ fn queries<'a>() -> Queries< if let Some(listing_type) = options.listing_type { match listing_type { - ListingType::Subscribed => { - query = query.filter(community_follower::person_id.is_not_null()) - } // TODO could be this: and(community_follower::person_id.eq(person_id_join)), + ListingType::Subscribed => query = query.filter(community_follower::pending.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Local => { query = query.filter(community::local.eq(true)).filter( community::hidden @@ -191,11 +189,16 @@ fn queries<'a>() -> Queries< } } - if options.saved_only.unwrap_or(false) { + if options.saved_only { query = query.filter(comment_saved::comment_id.is_not_null()); } - let is_profile_view = options.is_profile_view.unwrap_or(false); + if options.liked_only { + query = query.filter(comment_like::score.eq(1)); + } else if options.disliked_only { + query = query.filter(comment_like::score.eq(-1)); + } + let is_creator = options.creator_id == options.local_user.map(|l| l.person.id); // only show deleted comments to creator if !is_creator { @@ -204,7 +207,7 @@ fn queries<'a>() -> Queries< let is_admin = options.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) { + if !(options.is_profile_view && is_admin) { query = query.filter(comment::removed.eq(false)); } @@ -238,8 +241,8 @@ fn queries<'a>() -> Queries< query = query.filter(nlevel(comment::path).le(depth_limit)); - // only order if filtering by a post id. DOS potential otherwise and max_depth + !post_id isn't used anyways (afaik) - if options.post_id.is_some() { + // only order if filtering by a post id, or parent_path. DOS potential otherwise and max_depth + !post_id isn't used anyways (afaik) + if options.post_id.is_some() || options.parent_path.is_some() { // Always order by the parent path first query = query.order_by(subpath(comment::path, 0, -1)); } @@ -309,9 +312,10 @@ pub struct CommentQuery<'a> { pub creator_id: Option, pub local_user: Option<&'a LocalUserView>, pub search_term: Option, - pub saved_only: Option, - pub is_profile_view: Option, - pub show_deleted_and_removed: Option, + pub saved_only: bool, + pub liked_only: bool, + pub disliked_only: bool, + pub is_profile_view: bool, pub page: Option, pub limit: Option, pub max_depth: Option, @@ -332,10 +336,10 @@ impl JoinView for CommentView { post: a.2, community: a.3, counts: a.4, - creator_banned_from_community: a.5.is_some(), - subscribed: CommunityFollower::to_subscribed_type(&a.6), - saved: a.7.is_some(), - creator_blocked: a.8.is_some(), + creator_banned_from_community: a.5, + subscribed: a.6, + saved: a.7, + creator_blocked: a.8, my_vote: a.9, } } @@ -355,7 +359,6 @@ mod tests { Community, DbPool, Person, - PersonBlock, Post, }, structs::LocalUserView, @@ -372,7 +375,7 @@ mod tests { language::Language, local_user::{LocalUser, LocalUserInsertForm}, person::PersonInsertForm, - person_block::PersonBlockForm, + person_block::{PersonBlock, PersonBlockForm}, post::PostInsertForm, }, traits::{Blockable, Crud, Likeable}, @@ -610,6 +613,33 @@ mod tests { // Make sure block set the creator blocked assert!(read_comment_from_blocked_person.creator_blocked); + let read_liked_comment_views = CommentQuery { + local_user: (Some(&data.local_user_view)), + liked_only: (true), + ..Default::default() + } + .list(pool) + .await + .unwrap(); + + assert_eq!( + expected_comment_view_with_person, + read_liked_comment_views[0] + ); + + assert_eq!(1, read_liked_comment_views.len()); + + let read_disliked_comment_views: Vec = CommentQuery { + local_user: (Some(&data.local_user_view)), + disliked_only: (true), + ..Default::default() + } + .list(pool) + .await + .unwrap(); + + assert!(read_disliked_comment_views.is_empty()); + cleanup(data, pool).await; } diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index 4ef6067fd..07037f940 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -23,12 +23,7 @@ use lemmy_db_schema::{ post_like, post_report, }, - source::{ - community::{Community, CommunityPersonBan}, - person::Person, - post::Post, - post_report::PostReport, - }, + source::{community::Community, person::Person, post::Post, post_report::PostReport}, traits::JoinView, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, }; @@ -39,7 +34,7 @@ type PostReportViewTuple = ( Community, Person, Person, - Option, + bool, Option, PostAggregates, Option, @@ -80,7 +75,7 @@ fn queries<'a>() -> Queries< community::all_columns, person::all_columns, aliases::person1.fields(person::all_columns), - community_person_ban::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), post_like::score.nullable(), post_aggregates::all_columns, aliases::person2.fields(person::all_columns.nullable()), @@ -103,7 +98,7 @@ fn queries<'a>() -> Queries< query = query.filter(post::community_id.eq(community_id)); } - if options.unresolved_only.unwrap_or(false) { + if options.unresolved_only { query = query.filter(post_report::resolved.eq(false)); } @@ -191,7 +186,7 @@ pub struct PostReportQuery { pub community_id: Option, pub page: Option, pub limit: Option, - pub unresolved_only: Option, + pub unresolved_only: bool, } impl PostReportQuery { @@ -213,7 +208,7 @@ impl JoinView for PostReportView { community: a.2, creator: a.3, post_creator: a.4, - creator_banned_from_community: a.5.is_some(), + creator_banned_from_community: a.5, my_vote: a.6, counts: a.7, resolver: a.8, @@ -537,7 +532,7 @@ mod tests { // Do a batch read of timmys reports // It should only show saras, which is unresolved let reports_after_resolve = PostReportQuery { - unresolved_only: (Some(true)), + unresolved_only: (true), ..Default::default() } .list(pool, &inserted_timmy) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 3243bca88..f7add4cec 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -34,15 +34,15 @@ use lemmy_db_schema::{ post_saved, }, source::{ - community::{Community, CommunityFollower, CommunityPersonBan}, + community::{Community, CommunityFollower}, person::Person, - person_block::PersonBlock, - post::{Post, PostRead, PostSaved}, + post::Post, }, traits::JoinView, utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, ListingType, SortType, + SubscribedType, }; use tracing::debug; @@ -50,12 +50,12 @@ type PostViewTuple = ( Post, Person, Community, - Option, + bool, PostAggregates, - Option, - Option, - Option, - Option, + SubscribedType, + bool, + bool, + bool, Option, i64, ); @@ -63,7 +63,7 @@ type PostViewTuple = ( sql_function!(fn coalesce(x: sql_types::Nullable, y: sql_types::BigInt) -> sql_types::BigInt); fn queries<'a>() -> Queries< - impl ReadFn<'a, PostView, (PostId, Option, Option)>, + impl ReadFn<'a, PostView, (PostId, Option, bool)>, impl ListFn<'a, PostView, PostQuery<'a>>, > { let all_joins = |query: post_aggregates::BoxedQuery<'a, Pg>, my_person_id: Option| { @@ -136,12 +136,12 @@ fn queries<'a>() -> Queries< post::all_columns, person::all_columns, community::all_columns, - community_person_ban::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), post_aggregates::all_columns, - community_follower::all_columns.nullable(), - post_saved::all_columns.nullable(), - post_read::all_columns.nullable(), - person_block::all_columns.nullable(), + CommunityFollower::select_subscribed_type(), + post_saved::id.nullable().is_not_null(), + post_read::id.nullable().is_not_null(), + person_block::id.nullable().is_not_null(), post_like::score.nullable(), coalesce( post_aggregates::comments.nullable() - person_post_aggregates::read_comments.nullable(), @@ -149,43 +149,40 @@ fn queries<'a>() -> Queries< ), ); - let read = move |mut conn: DbConn<'a>, - (post_id, my_person_id, is_mod_or_admin): ( - PostId, - Option, - Option, - )| async move { - // The left join below will return None in this case - let person_id_join = my_person_id.unwrap_or(PersonId(-1)); + let read = + move |mut conn: DbConn<'a>, + (post_id, my_person_id, is_mod_or_admin): (PostId, Option, bool)| async move { + // The left join below will return None in this case + let person_id_join = my_person_id.unwrap_or(PersonId(-1)); - let mut query = all_joins( - post_aggregates::table - .filter(post_aggregates::post_id.eq(post_id)) - .into_boxed(), - my_person_id, - ) - .select(selection); + let mut query = all_joins( + post_aggregates::table + .filter(post_aggregates::post_id.eq(post_id)) + .into_boxed(), + my_person_id, + ) + .select(selection); - // Hide deleted and removed for non-admins or mods - if !is_mod_or_admin.unwrap_or(false) { - query = query - .filter(community::removed.eq(false)) - .filter(post::removed.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)), - ); - } + // Hide deleted and removed for non-admins or mods + if !is_mod_or_admin { + query = query + .filter(community::removed.eq(false)) + .filter(post::removed.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)), + ); + } - query.first::(&mut conn).await - }; + query.first::(&mut conn).await + }; let list = move |mut conn: DbConn<'a>, options: PostQuery<'a>| async move { let person_id = options.local_user.map(|l| l.person.id); @@ -212,7 +209,6 @@ fn queries<'a>() -> Queries< ) .select(selection); - let is_profile_view = options.is_profile_view.unwrap_or(false); let is_creator = options.creator_id == options.local_user.map(|l| l.person.id); // only show deleted posts to creator if is_creator { @@ -223,7 +219,7 @@ fn queries<'a>() -> Queries< let is_admin = options.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) { + if !(options.is_profile_view && is_admin) { query = query .filter(community::removed.eq(false)) .filter(post::removed.eq(false)); @@ -243,9 +239,7 @@ fn queries<'a>() -> Queries< if let Some(listing_type) = options.listing_type { match listing_type { - ListingType::Subscribed => { - query = query.filter(community_follower::person_id.is_not_null()) - } + ListingType::Subscribed => query = query.filter(community_follower::pending.is_not_null()), ListingType::Local => { query = query.filter(community::local.eq(true)).filter( community::hidden @@ -294,11 +288,11 @@ fn queries<'a>() -> Queries< query = query.filter(person::bot_account.eq(false)); }; - if options.saved_only.unwrap_or(false) { - query = query.filter(post_saved::post_id.is_not_null()); + if options.saved_only { + query = query.filter(post_saved::id.is_not_null()); } - if options.moderator_view.unwrap_or(false) { + if options.moderator_view { query = query.filter(community_moderator::person_id.is_not_null()); } // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read @@ -309,18 +303,24 @@ fn queries<'a>() -> Queries< .unwrap_or(true) { // Do not hide read posts when it is a user profile view - if !is_profile_view { + if !options.is_profile_view { query = query.filter(post_read::post_id.is_null()); } } + if options.liked_only { + query = query.filter(post_like::score.eq(1)); + } else if options.disliked_only { + query = query.filter(post_like::score.eq(-1)); + } + if options.local_user.is_some() { // Filter out the rows with missing languages query = query.filter(local_user_language::language_id.is_not_null()); // Don't show blocked communities or persons query = query.filter(community_block::person_id.is_null()); - if !options.moderator_view.unwrap_or(false) { + if !options.moderator_view { query = query.filter(person_block::person_id.is_null()); } } @@ -401,7 +401,7 @@ impl PostView { pool: &mut DbPool<'_>, post_id: PostId, my_person_id: Option, - is_mod_or_admin: Option, + is_mod_or_admin: bool, ) -> Result { let mut res = queries() .read(pool, (post_id, my_person_id, is_mod_or_admin)) @@ -426,9 +426,11 @@ pub struct PostQuery<'a> { pub local_user: Option<&'a LocalUserView>, pub search_term: Option, pub url_search: Option, - pub saved_only: Option, - pub moderator_view: Option, - pub is_profile_view: Option, + pub saved_only: bool, + pub liked_only: bool, + pub disliked_only: bool, + pub moderator_view: bool, + pub is_profile_view: bool, pub page: Option, pub limit: Option, } @@ -446,12 +448,12 @@ impl JoinView for PostView { post: a.0, creator: a.1, community: a.2, - creator_banned_from_community: a.3.is_some(), + creator_banned_from_community: a.3, counts: a.4, - subscribed: CommunityFollower::to_subscribed_type(&a.5), - saved: a.6.is_some(), - read: a.7.is_some(), - creator_blocked: a.8.is_some(), + subscribed: a.5, + saved: a.6, + read: a.7, + creator_blocked: a.8, my_vote: a.9, unread_comments: a.10, } @@ -603,9 +605,10 @@ mod tests { let pool = &mut pool.into(); let mut data = init_data(pool).await; - let local_user_form = LocalUserUpdateForm::builder() - .show_bot_accounts(Some(false)) - .build(); + let local_user_form = LocalUserUpdateForm { + show_bot_accounts: Some(false), + ..Default::default() + }; let inserted_local_user = LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form) .await @@ -626,7 +629,7 @@ mod tests { pool, data.inserted_post.id, Some(data.local_user_view.person.id), - None, + false, ) .await .unwrap(); @@ -643,9 +646,10 @@ mod tests { post_listing_single_with_person ); - let local_user_form = LocalUserUpdateForm::builder() - .show_bot_accounts(Some(true)) - .build(); + let local_user_form = LocalUserUpdateForm { + show_bot_accounts: Some(true), + ..Default::default() + }; let inserted_local_user = LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form) .await @@ -684,7 +688,7 @@ mod tests { .unwrap(); let read_post_listing_single_no_person = - PostView::read(pool, data.inserted_post.id, None, None) + PostView::read(pool, data.inserted_post.id, None, false) .await .unwrap(); @@ -764,7 +768,7 @@ mod tests { pool, data.inserted_post.id, Some(data.local_user_view.person.id), - None, + false, ) .await .unwrap(); @@ -775,9 +779,10 @@ mod tests { expected_post_with_upvote.counts.upvotes = 1; assert_eq!(expected_post_with_upvote, post_listing_single_with_person); - let local_user_form = LocalUserUpdateForm::builder() - .show_bot_accounts(Some(false)) - .build(); + let local_user_form = LocalUserUpdateForm { + show_bot_accounts: Some(false), + ..Default::default() + }; let inserted_local_user = LocalUser::update(pool, data.local_user_view.local_user.id, &local_user_form) .await @@ -797,6 +802,28 @@ mod tests { assert_eq!(expected_post_with_upvote, read_post_listing[0]); + let read_liked_post_listing = PostQuery { + community_id: (Some(data.inserted_community.id)), + local_user: (Some(&data.local_user_view)), + liked_only: (true), + ..Default::default() + } + .list(pool) + .await + .unwrap(); + assert_eq!(read_post_listing, read_liked_post_listing); + + let read_disliked_post_listing = PostQuery { + community_id: (Some(data.inserted_community.id)), + local_user: (Some(&data.local_user_view)), + disliked_only: (true), + ..Default::default() + } + .list(pool) + .await + .unwrap(); + assert!(read_disliked_post_listing.is_empty()); + let like_removed = PostLike::remove(pool, data.local_user_view.person.id, data.inserted_post.id) .await @@ -898,7 +925,10 @@ mod tests { Post::update( pool, data.inserted_post.id, - &PostUpdateForm::builder().removed(Some(true)).build(), + &PostUpdateForm { + removed: Some(true), + ..Default::default() + }, ) .await .unwrap(); @@ -919,7 +949,7 @@ mod tests { let post_listings_is_admin = PostQuery { sort: Some(SortType::New), local_user: Some(&data.local_user_view), - is_profile_view: Some(true), + is_profile_view: true, ..Default::default() } .list(pool) @@ -941,7 +971,10 @@ mod tests { Post::update( pool, data.inserted_post.id, - &PostUpdateForm::builder().deleted(Some(true)).build(), + &PostUpdateForm { + deleted: Some(true), + ..Default::default() + }, ) .await .unwrap(); diff --git a/crates/db_views/src/private_message_report_view.rs b/crates/db_views/src/private_message_report_view.rs index ce87abaec..f1dfa3f48 100644 --- a/crates/db_views/src/private_message_report_view.rs +++ b/crates/db_views/src/private_message_report_view.rs @@ -63,7 +63,7 @@ fn queries<'a>() -> Queries< let list = move |mut conn: DbConn<'a>, options: PrivateMessageReportQuery| async move { let mut query = all_joins(private_message_report::table.into_boxed()); - if options.unresolved_only.unwrap_or(false) { + if options.unresolved_only { query = query.filter(private_message_report::resolved.eq(false)); } @@ -110,7 +110,7 @@ impl PrivateMessageReportView { pub struct PrivateMessageReportQuery { pub page: Option, pub limit: Option, - pub unresolved_only: Option, + pub unresolved_only: bool, } impl PrivateMessageReportQuery { @@ -217,7 +217,7 @@ mod tests { .unwrap(); let reports = PrivateMessageReportQuery { - unresolved_only: (Some(false)), + unresolved_only: (false), ..Default::default() } .list(pool) diff --git a/crates/db_views/src/private_message_view.rs b/crates/db_views/src/private_message_view.rs index 55d6583ba..58f1f3f8a 100644 --- a/crates/db_views/src/private_message_view.rs +++ b/crates/db_views/src/private_message_view.rs @@ -52,10 +52,12 @@ fn queries<'a>() -> Queries< let mut query = all_joins(private_message::table.into_boxed()).select(selection); // If its unread, I only want the ones to me - if options.unread_only.unwrap_or(false) { - query = query - .filter(private_message::read.eq(false)) - .filter(private_message::recipient_id.eq(recipient_id)); + if options.unread_only { + query = query.filter(private_message::read.eq(false)); + if let Some(i) = options.creator_id { + query = query.filter(private_message::creator_id.eq(i)) + } + query = query.filter(private_message::recipient_id.eq(recipient_id)); } // Otherwise, I want the ALL view to show both sent and received else { @@ -63,7 +65,14 @@ fn queries<'a>() -> Queries< private_message::recipient_id .eq(recipient_id) .or(private_message::creator_id.eq(recipient_id)), - ) + ); + if let Some(i) = options.creator_id { + query = query.filter( + private_message::creator_id + .eq(i) + .or(private_message::recipient_id.eq(i)), + ) + } } let (limit, offset) = limit_and_offset(options.page, options.limit)?; @@ -112,9 +121,10 @@ impl PrivateMessageView { #[derive(Default)] pub struct PrivateMessageQuery { - pub unread_only: Option, + pub unread_only: bool, pub page: Option, pub limit: Option, + pub creator_id: Option, } impl PrivateMessageQuery { @@ -137,3 +147,154 @@ impl JoinView for PrivateMessageView { } } } + +#[cfg(test)] +mod tests { + #![allow(clippy::unwrap_used)] + #![allow(clippy::indexing_slicing)] + + use crate::private_message_view::PrivateMessageQuery; + use lemmy_db_schema::{ + source::{ + instance::Instance, + person::{Person, PersonInsertForm}, + private_message::{PrivateMessage, PrivateMessageInsertForm}, + }, + traits::Crud, + utils::build_db_pool_for_tests, + }; + use serial_test::serial; + + #[tokio::test] + #[serial] + async fn test_crud() { + let message_content = String::new(); + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + + let instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) + .await + .unwrap(); + + let timmy_form = PersonInsertForm::builder() + .name("timmy_rav".into()) + .admin(Some(true)) + .public_key("pubkey".to_string()) + .instance_id(instance.id) + .build(); + + let timmy = Person::create(pool, &timmy_form).await.unwrap(); + + let sara_form = PersonInsertForm::builder() + .name("sara_rav".into()) + .public_key("pubkey".to_string()) + .instance_id(instance.id) + .build(); + + let sara = Person::create(pool, &sara_form).await.unwrap(); + + let jess_form = PersonInsertForm::builder() + .name("jess_rav".into()) + .public_key("pubkey".to_string()) + .instance_id(instance.id) + .build(); + + let jess = Person::create(pool, &jess_form).await.unwrap(); + + let sara_timmy_message_form = PrivateMessageInsertForm::builder() + .creator_id(sara.id) + .recipient_id(timmy.id) + .content(message_content.clone()) + .build(); + let _inserted_sara_timmy_message_form = PrivateMessage::create(pool, &sara_timmy_message_form) + .await + .unwrap(); + + let sara_jess_message_form = PrivateMessageInsertForm::builder() + .creator_id(sara.id) + .recipient_id(jess.id) + .content(message_content.clone()) + .build(); + let _inserted_sara_jess_message_form = PrivateMessage::create(pool, &sara_jess_message_form) + .await + .unwrap(); + + let timmy_sara_message_form = PrivateMessageInsertForm::builder() + .creator_id(timmy.id) + .recipient_id(sara.id) + .content(message_content.clone()) + .build(); + let _inserted_timmy_sara_message_form = PrivateMessage::create(pool, &timmy_sara_message_form) + .await + .unwrap(); + + let jess_timmy_message_form = PrivateMessageInsertForm::builder() + .creator_id(jess.id) + .recipient_id(timmy.id) + .content(message_content.clone()) + .build(); + let _inserted_jess_timmy_message_form = PrivateMessage::create(pool, &jess_timmy_message_form) + .await + .unwrap(); + + let timmy_messages = PrivateMessageQuery { + unread_only: false, + creator_id: Option::None, + ..Default::default() + } + .list(pool, timmy.id) + .await + .unwrap(); + + assert_eq!(timmy_messages.len(), 3); + assert_eq!(timmy_messages[0].creator.id, jess.id); + assert_eq!(timmy_messages[0].recipient.id, timmy.id); + assert_eq!(timmy_messages[1].creator.id, timmy.id); + assert_eq!(timmy_messages[1].recipient.id, sara.id); + assert_eq!(timmy_messages[2].creator.id, sara.id); + assert_eq!(timmy_messages[2].recipient.id, timmy.id); + + let timmy_unread_messages = PrivateMessageQuery { + unread_only: true, + creator_id: Option::None, + ..Default::default() + } + .list(pool, timmy.id) + .await + .unwrap(); + + assert_eq!(timmy_unread_messages.len(), 2); + assert_eq!(timmy_unread_messages[0].creator.id, jess.id); + assert_eq!(timmy_unread_messages[0].recipient.id, timmy.id); + assert_eq!(timmy_unread_messages[1].creator.id, sara.id); + assert_eq!(timmy_unread_messages[1].recipient.id, timmy.id); + + let timmy_sara_messages = PrivateMessageQuery { + unread_only: false, + creator_id: Some(sara.id), + ..Default::default() + } + .list(pool, timmy.id) + .await + .unwrap(); + + assert_eq!(timmy_sara_messages.len(), 2); + assert_eq!(timmy_sara_messages[0].creator.id, timmy.id); + assert_eq!(timmy_sara_messages[0].recipient.id, sara.id); + assert_eq!(timmy_sara_messages[1].creator.id, sara.id); + assert_eq!(timmy_sara_messages[1].recipient.id, timmy.id); + + let timmy_sara_unread_messages = PrivateMessageQuery { + unread_only: true, + creator_id: Some(sara.id), + ..Default::default() + } + .list(pool, timmy.id) + .await + .unwrap(); + + assert_eq!(timmy_sara_unread_messages.len(), 1); + assert_eq!(timmy_sara_unread_messages[0].creator.id, sara.id); + assert_eq!(timmy_sara_unread_messages[0].recipient.id, timmy.id); + } +} diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs index 6064bf055..46556317f 100644 --- a/crates/db_views/src/registration_application_view.rs +++ b/crates/db_views/src/registration_application_view.rs @@ -58,11 +58,11 @@ fn queries<'a>() -> Queries< let list = move |mut conn: DbConn<'a>, options: RegistrationApplicationQuery| async move { let mut query = all_joins(registration_application::table.into_boxed()); - if options.unread_only.unwrap_or(false) { + if options.unread_only { query = query.filter(registration_application::admin_id.is_null()) } - if options.verified_email_only.unwrap_or(false) { + if options.verified_email_only { query = query.filter(local_user::email_verified.eq(true)) } @@ -120,8 +120,8 @@ impl RegistrationApplicationView { #[derive(Default)] pub struct RegistrationApplicationQuery { - pub unread_only: Option, - pub verified_email_only: Option, + pub unread_only: bool, + pub verified_email_only: bool, pub page: Option, pub limit: Option, } @@ -321,7 +321,7 @@ mod tests { // Do a batch read of the applications let apps = RegistrationApplicationQuery { - unread_only: (Some(true)), + unread_only: (true), ..Default::default() } .list(pool) @@ -350,9 +350,10 @@ mod tests { .unwrap(); // Update the local_user row - let approve_local_user_form = LocalUserUpdateForm::builder() - .accepted_application(Some(true)) - .build(); + let approve_local_user_form = LocalUserUpdateForm { + accepted_application: Some(true), + ..Default::default() + }; LocalUser::update(pool, inserted_sara_local_user.id, &approve_local_user_form) .await @@ -397,7 +398,7 @@ mod tests { // Do a batch read of apps again // It should show only jessicas which is unresolved let apps_after_resolve = RegistrationApplicationQuery { - unread_only: (Some(true)), + unread_only: (true), ..Default::default() } .list(pool) diff --git a/crates/db_views_actor/src/comment_reply_view.rs b/crates/db_views_actor/src/comment_reply_view.rs index 869345200..97d5b31eb 100644 --- a/crates/db_views_actor/src/comment_reply_view.rs +++ b/crates/db_views_actor/src/comment_reply_view.rs @@ -27,16 +27,16 @@ use lemmy_db_schema::{ post, }, source::{ - comment::{Comment, CommentSaved}, + comment::Comment, comment_reply::CommentReply, - community::{Community, CommunityFollower, CommunityPersonBan}, + community::{Community, CommunityFollower}, person::Person, - person_block::PersonBlock, post::Post, }, traits::JoinView, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, CommentSortType, + SubscribedType, }; type CommentReplyViewTuple = ( @@ -47,10 +47,10 @@ type CommentReplyViewTuple = ( Community, Person, CommentAggregates, - Option, - Option, - Option, - Option, + bool, + SubscribedType, + bool, + bool, Option, ); @@ -112,10 +112,10 @@ fn queries<'a>() -> Queries< community::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - community_person_ban::all_columns.nullable(), - community_follower::all_columns.nullable(), - comment_saved::all_columns.nullable(), - person_block::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), + CommunityFollower::select_subscribed_type(), + comment_saved::id.nullable().is_not_null(), + person_block::id.nullable().is_not_null(), comment_like::score.nullable(), )) }; @@ -138,11 +138,11 @@ fn queries<'a>() -> Queries< query = query.filter(comment_reply::recipient_id.eq(recipient_id)); } - if options.unread_only.unwrap_or(false) { + if options.unread_only { query = query.filter(comment_reply::read.eq(false)); } - if !options.show_bot_accounts.unwrap_or(true) { + if !options.show_bot_accounts { query = query.filter(person::bot_account.eq(false)); }; @@ -203,8 +203,8 @@ pub struct CommentReplyQuery { pub my_person_id: Option, pub recipient_id: Option, pub sort: Option, - pub unread_only: Option, - pub show_bot_accounts: Option, + pub unread_only: bool, + pub show_bot_accounts: bool, pub page: Option, pub limit: Option, } @@ -226,10 +226,10 @@ impl JoinView for CommentReplyView { community: a.4, recipient: a.5, counts: a.6, - creator_banned_from_community: a.7.is_some(), - subscribed: CommunityFollower::to_subscribed_type(&a.8), - saved: a.9.is_some(), - creator_blocked: a.10.is_some(), + creator_banned_from_community: a.7, + subscribed: a.8, + saved: a.9, + creator_blocked: a.10, my_vote: a.11, } } diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index 9ca5c218c..96c2e5891 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -16,24 +16,19 @@ use lemmy_db_schema::{ schema::{community, community_aggregates, community_block, community_follower, local_user}, source::{ community::{Community, CommunityFollower}, - community_block::CommunityBlock, local_user::LocalUser, }, traits::JoinView, utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, ListingType, SortType, + SubscribedType, }; -type CommunityViewTuple = ( - Community, - CommunityAggregates, - Option, - Option, -); +type CommunityViewTuple = (Community, CommunityAggregates, SubscribedType, bool); fn queries<'a>() -> Queries< - impl ReadFn<'a, CommunityView, (CommunityId, Option, Option)>, + impl ReadFn<'a, CommunityView, (CommunityId, Option, bool)>, impl ListFn<'a, CommunityView, CommunityQuery<'a>>, > { let all_joins = |query: community::BoxedQuery<'a, Pg>, my_person_id: Option| { @@ -61,8 +56,8 @@ fn queries<'a>() -> Queries< let selection = ( community::all_columns, community_aggregates::all_columns, - community_follower::all_columns.nullable(), - community_block::all_columns.nullable(), + CommunityFollower::select_subscribed_type(), + community_block::id.nullable().is_not_null(), ); let not_removed_or_deleted = community::removed @@ -73,7 +68,7 @@ fn queries<'a>() -> Queries< (community_id, my_person_id, is_mod_or_admin): ( CommunityId, Option, - Option, + bool, )| async move { let mut query = all_joins( community::table.find(community_id).into_boxed(), @@ -82,7 +77,7 @@ fn queries<'a>() -> Queries< .select(selection); // Hide deleted and removed for non-admins or mods - if !is_mod_or_admin.unwrap_or(false) { + if !is_mod_or_admin { query = query.filter(not_removed_or_deleted); } @@ -109,7 +104,7 @@ fn queries<'a>() -> Queries< } // Hide deleted and removed for non-admins or mods - if !options.is_mod_or_admin.unwrap_or(false) { + if !options.is_mod_or_admin { query = query.filter(not_removed_or_deleted).filter( community::hidden .eq(false) @@ -138,7 +133,7 @@ fn queries<'a>() -> Queries< if let Some(listing_type) = options.listing_type { query = match listing_type { - ListingType::Subscribed => query.filter(community_follower::person_id.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), + ListingType::Subscribed => query.filter(community_follower::pending.is_not_null()), // TODO could be this: and(community_follower::person_id.eq(person_id_join)), ListingType::Local => query.filter(community::local.eq(true)), _ => query, }; @@ -150,7 +145,7 @@ fn queries<'a>() -> Queries< query = query.filter(community::nsfw.eq(false).or(local_user::show_nsfw.eq(true))); } else { // No person in request, only show nsfw communities if show_nsfw is passed into request - if !options.show_nsfw.unwrap_or(false) { + if !options.show_nsfw { query = query.filter(community::nsfw.eq(false)); } } @@ -171,7 +166,7 @@ impl CommunityView { pool: &mut DbPool<'_>, community_id: CommunityId, my_person_id: Option, - is_mod_or_admin: Option, + is_mod_or_admin: bool, ) -> Result { queries() .read(pool, (community_id, my_person_id, is_mod_or_admin)) @@ -199,8 +194,8 @@ pub struct CommunityQuery<'a> { pub sort: Option, pub local_user: Option<&'a LocalUser>, pub search_term: Option, - pub is_mod_or_admin: Option, - pub show_nsfw: Option, + pub is_mod_or_admin: bool, + pub show_nsfw: bool, pub page: Option, pub limit: Option, } @@ -217,8 +212,8 @@ impl JoinView for CommunityView { Self { community: a.0, counts: a.1, - subscribed: CommunityFollower::to_subscribed_type(&a.2), - blocked: a.3.is_some(), + subscribed: a.2, + blocked: a.3, } } } diff --git a/crates/db_views_actor/src/person_mention_view.rs b/crates/db_views_actor/src/person_mention_view.rs index 6528ab5da..1a5544302 100644 --- a/crates/db_views_actor/src/person_mention_view.rs +++ b/crates/db_views_actor/src/person_mention_view.rs @@ -28,16 +28,16 @@ use lemmy_db_schema::{ post, }, source::{ - comment::{Comment, CommentSaved}, - community::{Community, CommunityFollower, CommunityPersonBan}, + comment::Comment, + community::{Community, CommunityFollower}, person::Person, - person_block::PersonBlock, person_mention::PersonMention, post::Post, }, traits::JoinView, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, CommentSortType, + SubscribedType, }; type PersonMentionViewTuple = ( @@ -48,10 +48,10 @@ type PersonMentionViewTuple = ( Community, Person, CommentAggregates, - Option, - Option, - Option, - Option, + bool, + SubscribedType, + bool, + bool, Option, ); @@ -108,10 +108,10 @@ fn queries<'a>() -> Queries< community::all_columns, aliases::person1.fields(person::all_columns), comment_aggregates::all_columns, - community_person_ban::all_columns.nullable(), - community_follower::all_columns.nullable(), - comment_saved::all_columns.nullable(), - person_block::all_columns.nullable(), + community_person_ban::id.nullable().is_not_null(), + CommunityFollower::select_subscribed_type(), + comment_saved::id.nullable().is_not_null(), + person_block::id.nullable().is_not_null(), comment_like::score.nullable(), ); @@ -154,11 +154,11 @@ fn queries<'a>() -> Queries< query = query.filter(person_mention::recipient_id.eq(recipient_id)); } - if options.unread_only.unwrap_or(false) { + if options.unread_only { query = query.filter(person_mention::read.eq(false)); } - if !options.show_bot_accounts.unwrap_or(true) { + if !options.show_bot_accounts { query = query.filter(person::bot_account.eq(false)); }; @@ -220,8 +220,8 @@ pub struct PersonMentionQuery { pub my_person_id: Option, pub recipient_id: Option, pub sort: Option, - pub unread_only: Option, - pub show_bot_accounts: Option, + pub unread_only: bool, + pub show_bot_accounts: bool, pub page: Option, pub limit: Option, } @@ -243,10 +243,10 @@ impl JoinView for PersonMentionView { community: a.4, recipient: a.5, counts: a.6, - creator_banned_from_community: a.7.is_some(), - subscribed: CommunityFollower::to_subscribed_type(&a.8), - saved: a.9.is_some(), - creator_blocked: a.10.is_some(), + creator_banned_from_community: a.7, + subscribed: a.8, + saved: a.9, + creator_blocked: a.10, my_vote: a.11, } } diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index 3abd8eed0..96e718631 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -373,7 +373,7 @@ async fn get_feed_inbox( let replies = CommentReplyQuery { recipient_id: (Some(person_id)), my_person_id: (Some(person_id)), - show_bot_accounts: (Some(show_bot_accounts)), + show_bot_accounts: (show_bot_accounts), sort: (Some(sort)), limit: (Some(RSS_FETCH_LIMIT)), ..Default::default() @@ -384,7 +384,7 @@ async fn get_feed_inbox( let mentions = PersonMentionQuery { recipient_id: (Some(person_id)), my_person_id: (Some(person_id)), - show_bot_accounts: (Some(show_bot_accounts)), + show_bot_accounts: (show_bot_accounts), sort: (Some(sort)), limit: (Some(RSS_FETCH_LIMIT)), ..Default::default() diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index 1539bae30..beb5d9b94 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -142,7 +142,7 @@ pub enum LemmyErrorType { InvalidQuery, ObjectNotLocal, PostIsLocked, - PersonIsBannedFromSite, + PersonIsBannedFromSite(String), InvalidVoteValue, PageDoesNotSpecifyCreator, PageDoesNotSpecifyGroup, @@ -207,6 +207,7 @@ pub enum LemmyErrorType { CouldntCreateAudioCaptcha, InvalidUrlScheme, CouldntSendWebmention, + ContradictingFilters, Unknown(String), } diff --git a/migrations/2023-08-02-144930_password-reset-token/down.sql b/migrations/2023-08-02-144930_password-reset-token/down.sql index 5f938da24..551d6fda3 100644 --- a/migrations/2023-08-02-144930_password-reset-token/down.sql +++ b/migrations/2023-08-02-144930_password-reset-token/down.sql @@ -1 +1,2 @@ -alter table password_reset_request rename column token to token_encrypted; +ALTER TABLE password_reset_request RENAME COLUMN token TO token_encrypted; + diff --git a/migrations/2023-08-02-144930_password-reset-token/up.sql b/migrations/2023-08-02-144930_password-reset-token/up.sql index 0bdd1655b..f0e1a407b 100644 --- a/migrations/2023-08-02-144930_password-reset-token/up.sql +++ b/migrations/2023-08-02-144930_password-reset-token/up.sql @@ -1 +1,2 @@ -alter table password_reset_request rename column token_encrypted to token; +ALTER TABLE password_reset_request RENAME COLUMN token_encrypted TO token; + diff --git a/src/code_migrations.rs b/src/code_migrations.rs index ae7df3979..51302524f 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -77,16 +77,17 @@ async fn user_updates_2020_04_02( for cperson in &incorrect_persons { let keypair = generate_actor_keypair()?; - let form = PersonUpdateForm::builder() - .actor_id(Some(generate_local_apub_endpoint( + let form = PersonUpdateForm { + actor_id: Some(generate_local_apub_endpoint( EndpointType::Person, &cperson.name, protocol_and_hostname, - )?)) - .private_key(Some(Some(keypair.private_key))) - .public_key(Some(keypair.public_key)) - .last_refreshed_at(Some(naive_now())) - .build(); + )?), + private_key: Some(Some(keypair.private_key)), + public_key: Some(keypair.public_key), + last_refreshed_at: Some(naive_now()), + ..Default::default() + }; Person::update(pool, cperson.id, &form).await?; } @@ -120,12 +121,13 @@ async fn community_updates_2020_04_02( protocol_and_hostname, )?; - let form = CommunityUpdateForm::builder() - .actor_id(Some(community_actor_id.clone())) - .private_key(Some(Some(keypair.private_key))) - .public_key(Some(keypair.public_key)) - .last_refreshed_at(Some(naive_now())) - .build(); + let form = CommunityUpdateForm { + actor_id: Some(community_actor_id.clone()), + private_key: Some(Some(keypair.private_key)), + public_key: Some(keypair.public_key), + last_refreshed_at: Some(naive_now()), + ..Default::default() + }; Community::update(pool, ccommunity.id, &form).await?; } @@ -160,7 +162,10 @@ async fn post_updates_2020_04_03( Post::update( pool, cpost.id, - &PostUpdateForm::builder().ap_id(Some(apub_id)).build(), + &PostUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await?; } @@ -195,7 +200,10 @@ async fn comment_updates_2020_04_03( Comment::update( pool, ccomment.id, - &CommentUpdateForm::builder().ap_id(Some(apub_id)).build(), + &CommentUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await?; } @@ -230,9 +238,10 @@ async fn private_message_updates_2020_05_05( PrivateMessage::update( pool, cpm.id, - &PrivateMessageUpdateForm::builder() - .ap_id(Some(apub_id)) - .build(), + &PrivateMessageUpdateForm { + ap_id: Some(apub_id), + ..Default::default() + }, ) .await?; } @@ -344,13 +353,14 @@ async fn instance_actor_2022_01_28( } let key_pair = generate_actor_keypair()?; let actor_id = Url::parse(protocol_and_hostname)?; - let site_form = SiteUpdateForm::builder() - .actor_id(Some(actor_id.clone().into())) - .last_refreshed_at(Some(naive_now())) - .inbox_url(Some(generate_site_inbox_url(&actor_id.into())?)) - .private_key(Some(Some(key_pair.private_key))) - .public_key(Some(key_pair.public_key)) - .build(); + let site_form = SiteUpdateForm { + actor_id: Some(actor_id.clone().into()), + last_refreshed_at: Some(naive_now()), + inbox_url: Some(generate_site_inbox_url(&actor_id.into())?), + private_key: Some(Some(key_pair.private_key)), + public_key: Some(key_pair.public_key), + ..Default::default() + }; Site::update(pool, site.id, &site_form).await?; } Ok(()) @@ -379,10 +389,11 @@ async fn regenerate_public_keys_2022_07_05(pool: &mut DbPool<'_>) -> Result<(), community_.name ); let key_pair = generate_actor_keypair()?; - let form = CommunityUpdateForm::builder() - .public_key(Some(key_pair.public_key)) - .private_key(Some(Some(key_pair.private_key))) - .build(); + let form = CommunityUpdateForm { + public_key: Some(key_pair.public_key), + private_key: Some(Some(key_pair.private_key)), + ..Default::default() + }; Community::update(&mut conn.into(), community_.id, &form).await?; } } @@ -401,10 +412,11 @@ async fn regenerate_public_keys_2022_07_05(pool: &mut DbPool<'_>) -> Result<(), person_.name ); let key_pair = generate_actor_keypair()?; - let form = PersonUpdateForm::builder() - .public_key(Some(key_pair.public_key)) - .private_key(Some(Some(key_pair.private_key))) - .build(); + let form = PersonUpdateForm { + public_key: Some(key_pair.public_key), + private_key: Some(Some(key_pair.private_key)), + ..Default::default() + }; Person::update(pool, person_.id, &form).await?; } } diff --git a/src/scheduled_tasks.rs b/src/scheduled_tasks.rs index 28315beaa..a93494727 100644 --- a/src/scheduled_tasks.rs +++ b/src/scheduled_tasks.rs @@ -364,6 +364,7 @@ fn update_instance_software(conn: &mut PgConnection, user_agent: &str) -> LemmyR let client = Client::builder() .user_agent(user_agent) .timeout(REQWEST_TIMEOUT) + .connect_timeout(REQWEST_TIMEOUT) .build()?; let instances = instance::table.get_results::(conn)?;