Dont send comment reply to user who has community blocked. Fixes #3684 (#4096)

* Dont send comment reply to user who has community blocked. Fixes #3684

* Adding source instance block check.

* Adding api test.

* Addressing PR comments.
This commit is contained in:
Dessalines 2023-11-09 06:03:25 -05:00 committed by GitHub
parent aaaf17486d
commit e00b0c9da2
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 294 additions and 110 deletions

View file

@ -9,14 +9,19 @@
"scripts": { "scripts": {
"lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check 'src/**/*.ts'", "lint": "tsc --noEmit && eslint --report-unused-disable-directives --ext .js,.ts,.tsx src && prettier --check 'src/**/*.ts'",
"fix": "prettier --write src && eslint --fix src", "fix": "prettier --write src && eslint --fix src",
"api-test": "jest -i follow.spec.ts && jest -i post.spec.ts && jest -i comment.spec.ts && jest -i private_message.spec.ts && jest -i user.spec.ts && jest -i community.spec.ts" "api-test": "jest -i follow.spec.ts && jest -i post.spec.ts && jest -i comment.spec.ts && jest -i private_message.spec.ts && jest -i user.spec.ts && jest -i community.spec.ts",
"api-test-comment": "jest -i comment.spec.ts",
"api-test-post": "jest -i post.spec.ts",
"api-test-user": "jest -i user.spec.ts",
"api-test-community": "jest -i community.spec.ts",
"api-test-private-message": "jest -i private_message.spec.ts"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^29.5.6", "@types/jest": "^29.5.8",
"@types/node": "^20.8.7", "@types/node": "^20.9.0",
"@typescript-eslint/eslint-plugin": "^6.8.0", "@typescript-eslint/eslint-plugin": "^6.10.0",
"@typescript-eslint/parser": "^6.8.0", "@typescript-eslint/parser": "^6.10.0",
"eslint": "^8.52.0", "eslint": "^8.53.0",
"eslint-plugin-prettier": "^5.0.1", "eslint-plugin-prettier": "^5.0.1",
"jest": "^29.5.0", "jest": "^29.5.0",
"lemmy-js-client": "0.19.0-rc.12", "lemmy-js-client": "0.19.0-rc.12",

View file

@ -35,9 +35,10 @@ import {
waitForPost, waitForPost,
alphaUrl, alphaUrl,
followCommunity, followCommunity,
blockCommunity,
delay,
} from "./shared"; } from "./shared";
import { CommentView } from "lemmy-js-client/dist/types/CommentView"; import { CommentView, CommunityView } from "lemmy-js-client";
import { CommunityView } from "lemmy-js-client";
import { LemmyHttp } from "lemmy-js-client"; import { LemmyHttp } from "lemmy-js-client";
let betaCommunity: CommunityView | undefined; let betaCommunity: CommunityView | undefined;
@ -740,3 +741,47 @@ test("Report a comment", async () => {
); );
expect(betaReport.reason).toBe(alphaReport.reason); expect(betaReport.reason).toBe(alphaReport.reason);
}); });
test("Dont send a comment reply to a blocked community", async () => {
let newCommunity = await createCommunity(beta);
let newCommunityId = newCommunity.community_view.community.id;
// Create a post on beta
let betaPost = await createPost(beta, newCommunityId);
let alphaPost = (await resolvePost(alpha, betaPost.post_view.post))!.post;
if (!alphaPost) {
throw "unable to locate post on alpha";
}
// Check beta's inbox count
let unreadCount = await getUnreadCount(beta);
expect(unreadCount.replies).toBe(1);
// Beta blocks the new beta community
let blockRes = await blockCommunity(beta, newCommunityId, true);
expect(blockRes.blocked).toBe(true);
delay();
// Alpha creates a comment
let commentRes = await createComment(alpha, alphaPost.post.id);
expect(commentRes.comment_view.comment.content).toBeDefined();
let alphaComment = await resolveComment(
beta,
commentRes.comment_view.comment,
);
if (!alphaComment) {
throw "Missing alpha comment before block";
}
// Check beta's inbox count, make sure it stays the same
unreadCount = await getUnreadCount(beta);
expect(unreadCount.replies).toBe(1);
let replies = await getReplies(beta);
expect(replies.replies.length).toBe(1);
// Unblock the community
blockRes = await blockCommunity(beta, newCommunityId, false);
expect(blockRes.blocked).toBe(false);
});

View file

@ -1,6 +1,9 @@
import { import {
BlockCommunity,
BlockCommunityResponse,
BlockInstance, BlockInstance,
BlockInstanceResponse, BlockInstanceResponse,
CommunityId,
GetReplies, GetReplies,
GetRepliesResponse, GetRepliesResponse,
GetUnreadCountResponse, GetUnreadCountResponse,
@ -796,6 +799,18 @@ export function blockInstance(
return api.blockInstance(form); return api.blockInstance(form);
} }
export function blockCommunity(
api: LemmyHttp,
community_id: CommunityId,
block: boolean,
): Promise<BlockCommunityResponse> {
let form: BlockCommunity = {
community_id,
block,
};
return api.blockCommunity(form);
}
export function delay(millis = 500) { export function delay(millis = 500) {
return new Promise(resolve => setTimeout(resolve, millis)); return new Promise(resolve => setTimeout(resolve, millis));
} }

View file

@ -314,10 +314,10 @@
resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4" resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.9.1.tgz#449dfa81a57a1d755b09aa58d826c1262e4283b4"
integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA== integrity sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==
"@eslint/eslintrc@^2.1.2": "@eslint/eslintrc@^2.1.3":
version "2.1.2" version "2.1.3"
resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.2.tgz#c6936b4b328c64496692f76944e755738be62396" resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.3.tgz#797470a75fe0fbd5a53350ee715e85e87baff22d"
integrity sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g== integrity sha512-yZzuIG+jnVu6hNSzFEN07e8BxF3uAzYtQb6uDkaYZLo6oYZDCq454c5kB8zxnzfCYyP4MIuyBn10L0DqwujTmA==
dependencies: dependencies:
ajv "^6.12.4" ajv "^6.12.4"
debug "^4.3.2" debug "^4.3.2"
@ -329,10 +329,10 @@
minimatch "^3.1.2" minimatch "^3.1.2"
strip-json-comments "^3.1.1" strip-json-comments "^3.1.1"
"@eslint/js@8.52.0": "@eslint/js@8.53.0":
version "8.52.0" version "8.53.0"
resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.52.0.tgz#78fe5f117840f69dc4a353adf9b9cd926353378c" resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.53.0.tgz#bea56f2ed2b5baea164348ff4d5a879f6f81f20d"
integrity sha512-mjZVbpaeMZludF2fsWLD0Z9gCref1Tk4i9+wddjRvpUNqqcndPkBD09N/Mapey0b3jaXbLm2kICwFv2E64QinA== integrity sha512-Kn7K8dx/5U6+cT1yEhpX1w4PCSg0M+XyRILPgvwcEBjerFWCwQj5sbr3/VmxqV0JGHCBCzyd6LxypEuehypY1w==
"@humanwhocodes/config-array@^0.11.13": "@humanwhocodes/config-array@^0.11.13":
version "0.11.13" version "0.11.13"
@ -704,10 +704,10 @@
dependencies: dependencies:
"@types/istanbul-lib-report" "*" "@types/istanbul-lib-report" "*"
"@types/jest@^29.5.6": "@types/jest@^29.5.8":
version "29.5.6" version "29.5.8"
resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.6.tgz#f4cf7ef1b5b0bfc1aa744e41b24d9cc52533130b" resolved "https://registry.yarnpkg.com/@types/jest/-/jest-29.5.8.tgz#ed5c256fe2bc7c38b1915ee5ef1ff24a3427e120"
integrity sha512-/t9NnzkOpXb4Nfvg17ieHE6EeSjDS2SGSpNYfoLbUAeL/EOueU/RSdOWFpfQTXBEM7BguYW1XQ0EbM+6RlIh6w== integrity sha512-fXEFTxMV2Co8ZF5aYFJv+YeA08RTYJfhtN5c9JSv/mFEMe+xxjufCb+PHL+bJcMs/ebPUsBu+UNTEz+ydXrR6g==
dependencies: dependencies:
expect "^29.0.0" expect "^29.0.0"
pretty-format "^29.0.0" pretty-format "^29.0.0"
@ -722,12 +722,12 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.0.tgz#10ddf0119cf20028781c06d7115562934e53f745" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.0.tgz#10ddf0119cf20028781c06d7115562934e53f745"
integrity sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ== integrity sha512-LzcWltT83s1bthcvjBmiBvGJiiUe84NWRHkw+ZV6Fr41z2FbIzvc815dk2nQ3RAKMuN2fkenM/z3Xv2QzEpYxQ==
"@types/node@^20.8.7": "@types/node@^20.9.0":
version "20.8.7" version "20.9.0"
resolved "https://registry.yarnpkg.com/@types/node/-/node-20.8.7.tgz#ad23827850843de973096edfc5abc9e922492a25" resolved "https://registry.yarnpkg.com/@types/node/-/node-20.9.0.tgz#bfcdc230583aeb891cf51e73cfdaacdd8deae298"
integrity sha512-21TKHHh3eUHIi2MloeptJWALuCu5H7HQTdTrWIFReA8ad+aggoX+lRes3ex7/FtpC+sVUpFMQ+QTfYr74mruiQ== integrity sha512-nekiGu2NDb1BcVofVcEKMIwzlx4NjHlcjhoxxKBNLtz15Y1z7MYf549DFvkHSId02Ax6kGwWntIBPC3l/JZcmw==
dependencies: dependencies:
undici-types "~5.25.1" undici-types "~5.26.4"
"@types/semver@^7.5.0": "@types/semver@^7.5.0":
version "7.5.3" version "7.5.3"
@ -751,16 +751,16 @@
dependencies: dependencies:
"@types/yargs-parser" "*" "@types/yargs-parser" "*"
"@typescript-eslint/eslint-plugin@^6.8.0": "@typescript-eslint/eslint-plugin@^6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.8.0.tgz#06abe4265e7c82f20ade2dcc0e3403c32d4f148b" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.10.0.tgz#cfe2bd34e26d2289212946b96ab19dcad64b661a"
integrity sha512-GosF4238Tkes2SHPQ1i8f6rMtG6zlKwMEB0abqSJ3Npvos+doIlc/ATG+vX1G9coDF3Ex78zM3heXHLyWEwLUw== integrity sha512-uoLj4g2OTL8rfUQVx2AFO1hp/zja1wABJq77P6IclQs6I/m9GLrm7jCdgzZkvWdDCQf1uEvoa8s8CupsgWQgVg==
dependencies: dependencies:
"@eslint-community/regexpp" "^4.5.1" "@eslint-community/regexpp" "^4.5.1"
"@typescript-eslint/scope-manager" "6.8.0" "@typescript-eslint/scope-manager" "6.10.0"
"@typescript-eslint/type-utils" "6.8.0" "@typescript-eslint/type-utils" "6.10.0"
"@typescript-eslint/utils" "6.8.0" "@typescript-eslint/utils" "6.10.0"
"@typescript-eslint/visitor-keys" "6.8.0" "@typescript-eslint/visitor-keys" "6.10.0"
debug "^4.3.4" debug "^4.3.4"
graphemer "^1.4.0" graphemer "^1.4.0"
ignore "^5.2.4" ignore "^5.2.4"
@ -768,72 +768,72 @@
semver "^7.5.4" semver "^7.5.4"
ts-api-utils "^1.0.1" ts-api-utils "^1.0.1"
"@typescript-eslint/parser@^6.8.0": "@typescript-eslint/parser@^6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.8.0.tgz#bb2a969d583db242f1ee64467542f8b05c2e28cb" resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.10.0.tgz#578af79ae7273193b0b6b61a742a2bc8e02f875a"
integrity sha512-5tNs6Bw0j6BdWuP8Fx+VH4G9fEPDxnVI7yH1IAPkQH5RUtvKwRoqdecAPdQXv4rSOADAaz1LFBZvZG7VbXivSg== integrity sha512-+sZwIj+s+io9ozSxIWbNB5873OSdfeBEH/FR0re14WLI6BaKuSOnnwCJ2foUiu8uXf4dRp1UqHP0vrZ1zXGrog==
dependencies: dependencies:
"@typescript-eslint/scope-manager" "6.8.0" "@typescript-eslint/scope-manager" "6.10.0"
"@typescript-eslint/types" "6.8.0" "@typescript-eslint/types" "6.10.0"
"@typescript-eslint/typescript-estree" "6.8.0" "@typescript-eslint/typescript-estree" "6.10.0"
"@typescript-eslint/visitor-keys" "6.8.0" "@typescript-eslint/visitor-keys" "6.10.0"
debug "^4.3.4" debug "^4.3.4"
"@typescript-eslint/scope-manager@6.8.0": "@typescript-eslint/scope-manager@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.8.0.tgz#5cac7977385cde068ab30686889dd59879811efd" resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.10.0.tgz#b0276118b13d16f72809e3cecc86a72c93708540"
integrity sha512-xe0HNBVwCph7rak+ZHcFD6A+q50SMsFwcmfdjs9Kz4qDh5hWhaPhFjRs/SODEhroBI5Ruyvyz9LfwUJ624O40g== integrity sha512-TN/plV7dzqqC2iPNf1KrxozDgZs53Gfgg5ZHyw8erd6jd5Ta/JIEcdCheXFt9b1NYb93a1wmIIVW/2gLkombDg==
dependencies: dependencies:
"@typescript-eslint/types" "6.8.0" "@typescript-eslint/types" "6.10.0"
"@typescript-eslint/visitor-keys" "6.8.0" "@typescript-eslint/visitor-keys" "6.10.0"
"@typescript-eslint/type-utils@6.8.0": "@typescript-eslint/type-utils@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.8.0.tgz#50365e44918ca0fd159844b5d6ea96789731e11f" resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.10.0.tgz#1007faede067c78bdbcef2e8abb31437e163e2e1"
integrity sha512-RYOJdlkTJIXW7GSldUIHqc/Hkto8E+fZN96dMIFhuTJcQwdRoGN2rEWA8U6oXbLo0qufH7NPElUb+MceHtz54g== integrity sha512-wYpPs3hgTFblMYwbYWPT3eZtaDOjbLyIYuqpwuLBBqhLiuvJ+9sEp2gNRJEtR5N/c9G1uTtQQL5AhV0fEPJYcg==
dependencies: dependencies:
"@typescript-eslint/typescript-estree" "6.8.0" "@typescript-eslint/typescript-estree" "6.10.0"
"@typescript-eslint/utils" "6.8.0" "@typescript-eslint/utils" "6.10.0"
debug "^4.3.4" debug "^4.3.4"
ts-api-utils "^1.0.1" ts-api-utils "^1.0.1"
"@typescript-eslint/types@6.8.0": "@typescript-eslint/types@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.8.0.tgz#1ab5d4fe1d613e3f65f6684026ade6b94f7e3ded" resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.10.0.tgz#f4f0a84aeb2ac546f21a66c6e0da92420e921367"
integrity sha512-p5qOxSum7W3k+llc7owEStXlGmSl8FcGvhYt8Vjy7FqEnmkCVlM3P57XQEGj58oqaBWDQXbJDZxwUWMS/EAPNQ== integrity sha512-36Fq1PWh9dusgo3vH7qmQAj5/AZqARky1Wi6WpINxB6SkQdY5vQoT2/7rW7uBIsPDcvvGCLi4r10p0OJ7ITAeg==
"@typescript-eslint/typescript-estree@6.8.0": "@typescript-eslint/typescript-estree@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.8.0.tgz#9565f15e0cd12f55cf5aa0dfb130a6cb0d436ba1" resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.10.0.tgz#667381eed6f723a1a8ad7590a31f312e31e07697"
integrity sha512-ISgV0lQ8XgW+mvv5My/+iTUdRmGspducmQcDw5JxznasXNnZn3SKNrTRuMsEXv+V/O+Lw9AGcQCfVaOPCAk/Zg== integrity sha512-ek0Eyuy6P15LJVeghbWhSrBCj/vJpPXXR+EpaRZqou7achUWL8IdYnMSC5WHAeTWswYQuP2hAZgij/bC9fanBg==
dependencies: dependencies:
"@typescript-eslint/types" "6.8.0" "@typescript-eslint/types" "6.10.0"
"@typescript-eslint/visitor-keys" "6.8.0" "@typescript-eslint/visitor-keys" "6.10.0"
debug "^4.3.4" debug "^4.3.4"
globby "^11.1.0" globby "^11.1.0"
is-glob "^4.0.3" is-glob "^4.0.3"
semver "^7.5.4" semver "^7.5.4"
ts-api-utils "^1.0.1" ts-api-utils "^1.0.1"
"@typescript-eslint/utils@6.8.0": "@typescript-eslint/utils@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.8.0.tgz#d42939c2074c6b59844d0982ce26a51d136c4029" resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.10.0.tgz#4d76062d94413c30e402c9b0df8c14aef8d77336"
integrity sha512-dKs1itdE2qFG4jr0dlYLQVppqTE+Itt7GmIf/vX6CSvsW+3ov8PbWauVKyyfNngokhIO9sKZeRGCUo1+N7U98Q== integrity sha512-v+pJ1/RcVyRc0o4wAGux9x42RHmAjIGzPRo538Z8M1tVx6HOnoQBCX/NoadHQlZeC+QO2yr4nNSFWOoraZCAyg==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.4.0" "@eslint-community/eslint-utils" "^4.4.0"
"@types/json-schema" "^7.0.12" "@types/json-schema" "^7.0.12"
"@types/semver" "^7.5.0" "@types/semver" "^7.5.0"
"@typescript-eslint/scope-manager" "6.8.0" "@typescript-eslint/scope-manager" "6.10.0"
"@typescript-eslint/types" "6.8.0" "@typescript-eslint/types" "6.10.0"
"@typescript-eslint/typescript-estree" "6.8.0" "@typescript-eslint/typescript-estree" "6.10.0"
semver "^7.5.4" semver "^7.5.4"
"@typescript-eslint/visitor-keys@6.8.0": "@typescript-eslint/visitor-keys@6.10.0":
version "6.8.0" version "6.10.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.8.0.tgz#cffebed56ae99c45eba901c378a6447b06be58b8" resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.10.0.tgz#b9eaf855a1ac7e95633ae1073af43d451e8f84e3"
integrity sha512-oqAnbA7c+pgOhW2OhGvxm0t1BULX5peQI/rLsNDpGM78EebV3C9IGbX5HNZabuZ6UQrYveCLjKo8Iy/lLlBkkg== integrity sha512-xMGluxQIEtOM7bqFCo+rCMh5fqI+ZxV5RUUOa29iVPz1OgCZrtc7rFnz5cLUazlkPKYqX+75iuDq7m0HQ48nCg==
dependencies: dependencies:
"@typescript-eslint/types" "6.8.0" "@typescript-eslint/types" "6.10.0"
eslint-visitor-keys "^3.4.1" eslint-visitor-keys "^3.4.1"
"@ungap/structured-clone@^1.2.0": "@ungap/structured-clone@^1.2.0":
@ -1333,15 +1333,15 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
eslint@^8.52.0: eslint@^8.53.0:
version "8.52.0" version "8.53.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.52.0.tgz#d0cd4a1fac06427a61ef9242b9353f36ea7062fc" resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.53.0.tgz#14f2c8244298fcae1f46945459577413ba2697ce"
integrity sha512-zh/JHnaixqHZsolRB/w9/02akBk9EPrOs9JwcTP2ek7yL5bVvXuRariiaAjjoJ5DvuwQ1WAE/HsMz+w17YgBCg== integrity sha512-N4VuiPjXDUa4xVeV/GC/RV3hQW9Nw+Y463lkWaKKXKYMvmRiRDAtfpuPFLN+E1/6ZhyR8J2ig+eVREnYgUsiag==
dependencies: dependencies:
"@eslint-community/eslint-utils" "^4.2.0" "@eslint-community/eslint-utils" "^4.2.0"
"@eslint-community/regexpp" "^4.6.1" "@eslint-community/regexpp" "^4.6.1"
"@eslint/eslintrc" "^2.1.2" "@eslint/eslintrc" "^2.1.3"
"@eslint/js" "8.52.0" "@eslint/js" "8.53.0"
"@humanwhocodes/config-array" "^0.11.13" "@humanwhocodes/config-array" "^0.11.13"
"@humanwhocodes/module-importer" "^1.0.1" "@humanwhocodes/module-importer" "^1.0.1"
"@nodelib/fs.walk" "^1.2.8" "@nodelib/fs.walk" "^1.2.8"
@ -2952,10 +2952,10 @@ typescript@^5.0.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.2.2.tgz#5ebb5e5a5b75f085f22bc3f8460fba308310fa78"
integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w== integrity sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==
undici-types@~5.25.1: undici-types@~5.26.4:
version "5.25.3" version "5.26.5"
resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.25.3.tgz#e044115914c85f0bcbb229f346ab739f064998c3" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-5.26.5.tgz#bcd539893d00b56e964fd2657a4866b221a65617"
integrity sha512-Ga1jfYwRn7+cP9v8auvEXN1rX3sWqlayd4HP7OKk4mZWylEmu3KzXDUGrQUN6Ol7qo1gPvB2e5gX6udnyEPgdA== integrity sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==
untildify@^4.0.0: untildify@^4.0.0:
version "4.0.0" version "4.0.0"

View file

@ -3,7 +3,12 @@ use crate::{
community::CommunityResponse, community::CommunityResponse,
context::LemmyContext, context::LemmyContext,
post::PostResponse, post::PostResponse,
utils::{check_person_block, get_interface_language, is_mod_or_admin, send_email_to_user}, utils::{
check_person_instance_community_block,
get_interface_language,
is_mod_or_admin,
send_email_to_user,
},
}; };
use actix_web::web::Json; use actix_web::web::Json;
use lemmy_db_schema::{ use lemmy_db_schema::{
@ -95,6 +100,8 @@ pub async fn send_local_notifs(
let mut recipient_ids = Vec::new(); let mut recipient_ids = Vec::new();
let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname()); let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname());
let community_id = post.community_id;
// Send the local mentions // Send the local mentions
for mention in mentions for mention in mentions
.iter() .iter()
@ -142,13 +149,18 @@ pub async fn send_local_notifs(
// Get the parent commenter local_user // Get the parent commenter local_user
let parent_creator_id = parent_comment.creator_id; let parent_creator_id = parent_comment.creator_id;
// Only add to recipients if that person isn't blocked let check_blocks = check_person_instance_community_block(
let creator_blocked = check_person_block(person.id, parent_creator_id, &mut context.pool()) person.id,
parent_creator_id,
person.instance_id,
community_id,
&mut context.pool(),
)
.await .await
.is_err(); .is_err();
// Don't send a notif to yourself // Don't send a notif to yourself
if parent_comment.creator_id != person.id && !creator_blocked { if parent_comment.creator_id != person.id && !check_blocks {
let user_view = LocalUserView::read_person(&mut context.pool(), parent_creator_id).await; let user_view = LocalUserView::read_person(&mut context.pool(), parent_creator_id).await;
if let Ok(parent_user_view) = user_view { if let Ok(parent_user_view) = user_view {
recipient_ids.push(parent_user_view.local_user.id); recipient_ids.push(parent_user_view.local_user.id);
@ -179,13 +191,17 @@ pub async fn send_local_notifs(
} }
} }
} else { } else {
// If there's no parent, its the post creator let check_blocks = check_person_instance_community_block(
// Only add to recipients if that person isn't blocked person.id,
let creator_blocked = check_person_block(person.id, post.creator_id, &mut context.pool()) post.creator_id,
person.instance_id,
community_id,
&mut context.pool(),
)
.await .await
.is_err(); .is_err();
if post.creator_id != person.id && !creator_blocked { if post.creator_id != person.id && !check_blocks {
let creator_id = post.creator_id; let creator_id = post.creator_id;
let parent_user = LocalUserView::read_person(&mut context.pool(), creator_id).await; let parent_user = LocalUserView::read_person(&mut context.pool(), creator_id).await;
if let Ok(parent_user_view) = parent_user { if let Ok(parent_user_view) = parent_user {

View file

@ -7,12 +7,14 @@ use anyhow::Context;
use chrono::{DateTime, Days, Local, TimeZone, Utc}; use chrono::{DateTime, Days, Local, TimeZone, Utc};
use enum_map::{enum_map, EnumMap}; use enum_map::{enum_map, EnumMap};
use lemmy_db_schema::{ use lemmy_db_schema::{
newtypes::{CommunityId, DbUrl, PersonId, PostId}, newtypes::{CommunityId, DbUrl, InstanceId, PersonId, PostId},
source::{ source::{
comment::{Comment, CommentUpdateForm}, comment::{Comment, CommentUpdateForm},
community::{Community, CommunityModerator, CommunityUpdateForm}, community::{Community, CommunityModerator, CommunityUpdateForm},
community_block::CommunityBlock,
email_verification::{EmailVerification, EmailVerificationForm}, email_verification::{EmailVerification, EmailVerificationForm},
instance::Instance, instance::Instance,
instance_block::InstanceBlock,
local_site::LocalSite, local_site::LocalSite,
local_site_rate_limit::LocalSiteRateLimit, local_site_rate_limit::LocalSiteRateLimit,
password_reset_request::PasswordResetRequest, password_reset_request::PasswordResetRequest,
@ -220,15 +222,14 @@ pub fn check_post_deleted_or_removed(post: &Post) -> Result<(), LemmyError> {
} }
} }
/// Throws an error if a recipient has blocked a person.
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub async fn check_person_block( pub async fn check_person_block(
my_id: PersonId, my_id: PersonId,
potential_blocker_id: PersonId, potential_blocker_id: PersonId,
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> { ) -> Result<(), LemmyError> {
let is_blocked = PersonBlock::read(pool, potential_blocker_id, my_id) let is_blocked = PersonBlock::read(pool, potential_blocker_id, my_id).await?;
.await
.is_ok();
if is_blocked { if is_blocked {
Err(LemmyErrorType::PersonIsBlocked)? Err(LemmyErrorType::PersonIsBlocked)?
} else { } else {
@ -236,6 +237,50 @@ pub async fn check_person_block(
} }
} }
/// Throws an error if a recipient has blocked a community.
#[tracing::instrument(skip_all)]
async fn check_community_block(
community_id: CommunityId,
person_id: PersonId,
pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> {
let is_blocked = CommunityBlock::read(pool, person_id, community_id).await?;
if is_blocked {
Err(LemmyErrorType::CommunityIsBlocked)?
} else {
Ok(())
}
}
/// Throws an error if a recipient has blocked an instance.
#[tracing::instrument(skip_all)]
async fn check_instance_block(
instance_id: InstanceId,
person_id: PersonId,
pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> {
let is_blocked = InstanceBlock::read(pool, person_id, instance_id).await?;
if is_blocked {
Err(LemmyErrorType::InstanceIsBlocked)?
} else {
Ok(())
}
}
#[tracing::instrument(skip_all)]
pub async fn check_person_instance_community_block(
my_id: PersonId,
potential_blocker_id: PersonId,
instance_id: InstanceId,
community_id: CommunityId,
pool: &mut DbPool<'_>,
) -> Result<(), LemmyError> {
check_person_block(my_id, potential_blocker_id, pool).await?;
check_instance_block(instance_id, potential_blocker_id, pool).await?;
check_community_block(community_id, potential_blocker_id, pool).await?;
Ok(())
}
#[tracing::instrument(skip_all)] #[tracing::instrument(skip_all)]
pub fn check_downvotes_enabled(score: i16, local_site: &LocalSite) -> Result<(), LemmyError> { pub fn check_downvotes_enabled(score: i16, local_site: &LocalSite) -> Result<(), LemmyError> {
if score == -1 && !local_site.enable_downvotes { if score == -1 && !local_site.enable_downvotes {

View file

@ -1,12 +1,36 @@
use crate::{ use crate::{
newtypes::{CommunityId, PersonId},
schema::community_block::dsl::{community_block, community_id, person_id}, schema::community_block::dsl::{community_block, community_id, person_id},
source::community_block::{CommunityBlock, CommunityBlockForm}, source::community_block::{CommunityBlock, CommunityBlockForm},
traits::Blockable, traits::Blockable,
utils::{get_conn, DbPool}, utils::{get_conn, DbPool},
}; };
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; use diesel::{
dsl::{exists, insert_into},
result::Error,
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
impl CommunityBlock {
pub async fn read(
pool: &mut DbPool<'_>,
for_person_id: PersonId,
for_community_id: CommunityId,
) -> Result<bool, Error> {
let conn = &mut get_conn(pool).await?;
select(exists(
community_block
.filter(community_id.eq(for_community_id))
.filter(person_id.eq(for_person_id)),
))
.get_result(conn)
.await
}
}
#[async_trait] #[async_trait]
impl Blockable for CommunityBlock { impl Blockable for CommunityBlock {
type Form = CommunityBlockForm; type Form = CommunityBlockForm;

View file

@ -1,12 +1,36 @@
use crate::{ use crate::{
newtypes::{InstanceId, PersonId},
schema::instance_block::dsl::{instance_block, instance_id, person_id}, schema::instance_block::dsl::{instance_block, instance_id, person_id},
source::instance_block::{InstanceBlock, InstanceBlockForm}, source::instance_block::{InstanceBlock, InstanceBlockForm},
traits::Blockable, traits::Blockable,
utils::{get_conn, DbPool}, utils::{get_conn, DbPool},
}; };
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; use diesel::{
dsl::{exists, insert_into},
result::Error,
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
impl InstanceBlock {
pub async fn read(
pool: &mut DbPool<'_>,
for_person_id: PersonId,
for_instance_id: InstanceId,
) -> Result<bool, Error> {
let conn = &mut get_conn(pool).await?;
select(exists(
instance_block
.filter(instance_id.eq(for_instance_id))
.filter(person_id.eq(for_person_id)),
))
.get_result(conn)
.await
}
}
#[async_trait] #[async_trait]
impl Blockable for InstanceBlock { impl Blockable for InstanceBlock {
type Form = InstanceBlockForm; type Form = InstanceBlockForm;

View file

@ -5,7 +5,13 @@ use crate::{
traits::Blockable, traits::Blockable,
utils::{get_conn, DbPool}, utils::{get_conn, DbPool},
}; };
use diesel::{dsl::insert_into, result::Error, ExpressionMethods, QueryDsl}; use diesel::{
dsl::{exists, insert_into},
result::Error,
select,
ExpressionMethods,
QueryDsl,
};
use diesel_async::RunQueryDsl; use diesel_async::RunQueryDsl;
impl PersonBlock { impl PersonBlock {
@ -13,12 +19,14 @@ impl PersonBlock {
pool: &mut DbPool<'_>, pool: &mut DbPool<'_>,
for_person_id: PersonId, for_person_id: PersonId,
for_recipient_id: PersonId, for_recipient_id: PersonId,
) -> Result<Self, Error> { ) -> Result<bool, Error> {
let conn = &mut get_conn(pool).await?; let conn = &mut get_conn(pool).await?;
select(exists(
person_block person_block
.filter(person_id.eq(for_person_id)) .filter(person_id.eq(for_person_id))
.filter(target_id.eq(for_recipient_id)) .filter(target_id.eq(for_recipient_id)),
.first::<Self>(conn) ))
.get_result(conn)
.await .await
} }
} }

View file

@ -110,6 +110,8 @@ pub enum LemmyErrorType {
CouldntFindCommunity, CouldntFindCommunity,
CouldntFindPerson, CouldntFindPerson,
PersonIsBlocked, PersonIsBlocked,
CommunityIsBlocked,
InstanceIsBlocked,
DownvotesAreDisabled, DownvotesAreDisabled,
InstanceIsPrivate, InstanceIsPrivate,
/// Password must be between 10 and 60 characters /// Password must be between 10 and 60 characters