From 6d8d23130d4b70d52437cce7152d39ab3e37d7eb Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 20 Jun 2024 06:44:06 -0400 Subject: [PATCH 01/69] Adding an image_details table to store image dimensions. (#4704) * Adding an image_details table to store image dimensions. - Adds an image_details table, which stores the height, width, and content_type for local and remote images. - For LocalImages, this information already comes back with the upload. - For RemoteImages, it calls the pictrs details endpoint. - Fixed some issues with proxying non-image urls. - Fixes #3328 - Also fixes #4703 * Running sql format. * Running fmt. * Don't fetch metadata in background for local API requests. * Dont export remote_image table to typescript. * Cleaning up validate. * Dont proxy url. * Fixing tests, fixing issue with federated thumbnails. * Fix tests. * Updating corepack, fixing issue. * Refactoring image inserts to use transactions. * Use select exists again. * Fixing imports. * Fix test. * Removing pointless backgrounded metadata generation version. * Removing public pictrs details route. * Fixing clippy. * Running prettier. * A few more fixes. * Moving diesel schema check back down. * Addressing PR comments. * Changing back request head to get. * Fixing lockfile. --------- Co-authored-by: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> --- api_tests/.eslintrc.json | 42 ----- api_tests/eslint.config.mjs | 56 ++++++ api_tests/package.json | 7 +- api_tests/pnpm-lock.yaml | 173 +++++++++++++++++- api_tests/prepare-drone-federation-test.sh | 2 +- api_tests/src/image.spec.ts | 4 + api_tests/src/post.spec.ts | 2 +- crates/api_common/src/request.rs | 58 +++++- crates/api_common/src/utils.rs | 32 +++- crates/db_schema/src/impls/images.rs | 78 ++++++-- crates/db_schema/src/schema.rs | 13 +- crates/db_schema/src/source/images.rs | 33 +++- crates/db_views/src/post_view.rs | 4 + crates/db_views/src/structs.rs | 3 +- crates/routes/src/images.rs | 8 +- .../down.sql | 7 + .../up.sql | 15 ++ 17 files changed, 453 insertions(+), 84 deletions(-) delete mode 100644 api_tests/.eslintrc.json create mode 100644 api_tests/eslint.config.mjs create mode 100644 migrations/2024-05-05-162540_add_image_detail_table/down.sql create mode 100644 migrations/2024-05-05-162540_add_image_detail_table/up.sql diff --git a/api_tests/.eslintrc.json b/api_tests/.eslintrc.json deleted file mode 100644 index 75b1706aa..000000000 --- a/api_tests/.eslintrc.json +++ /dev/null @@ -1,42 +0,0 @@ -{ - "root": true, - "env": { - "browser": true - }, - "plugins": ["@typescript-eslint"], - "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended"], - "parser": "@typescript-eslint/parser", - "parserOptions": { - "project": "./tsconfig.json", - "warnOnUnsupportedTypeScriptVersion": false - }, - "rules": { - "@typescript-eslint/ban-ts-comment": 0, - "@typescript-eslint/no-explicit-any": 0, - "@typescript-eslint/explicit-module-boundary-types": 0, - "@typescript-eslint/no-var-requires": 0, - "arrow-body-style": 0, - "curly": 0, - "eol-last": 0, - "eqeqeq": 0, - "func-style": 0, - "import/no-duplicates": 0, - "max-statements": 0, - "max-params": 0, - "new-cap": 0, - "no-console": 0, - "no-duplicate-imports": 0, - "no-extra-parens": 0, - "no-return-assign": 0, - "no-throw-literal": 0, - "no-trailing-spaces": 0, - "no-unused-expressions": 0, - "no-useless-constructor": 0, - "no-useless-escape": 0, - "no-var": 0, - "prefer-const": 0, - "prefer-rest-params": 0, - "quote-props": 0, - "unicorn/filename-case": 0 - } -} diff --git a/api_tests/eslint.config.mjs b/api_tests/eslint.config.mjs new file mode 100644 index 000000000..cf2c426d0 --- /dev/null +++ b/api_tests/eslint.config.mjs @@ -0,0 +1,56 @@ +import pluginJs from "@eslint/js"; +import tseslint from "typescript-eslint"; + +export default [ + pluginJs.configs.recommended, + ...tseslint.configs.recommended, + { + languageOptions: { + parser: tseslint.parser, + }, + }, + // For some reason this has to be in its own block + { + ignores: [ + "putTypesInIndex.js", + "dist/*", + "docs/*", + ".yalc", + "jest.config.js", + ], + }, + { + files: ["src/**/*"], + rules: { + "@typescript-eslint/no-empty-interface": 0, + "@typescript-eslint/no-empty-function": 0, + "@typescript-eslint/ban-ts-comment": 0, + "@typescript-eslint/no-explicit-any": 0, + "@typescript-eslint/explicit-module-boundary-types": 0, + "@typescript-eslint/no-var-requires": 0, + "arrow-body-style": 0, + curly: 0, + "eol-last": 0, + eqeqeq: 0, + "func-style": 0, + "import/no-duplicates": 0, + "max-statements": 0, + "max-params": 0, + "new-cap": 0, + "no-console": 0, + "no-duplicate-imports": 0, + "no-extra-parens": 0, + "no-return-assign": 0, + "no-throw-literal": 0, + "no-trailing-spaces": 0, + "no-unused-expressions": 0, + "no-useless-constructor": 0, + "no-useless-escape": 0, + "no-var": 0, + "prefer-const": 0, + "prefer-rest-params": 0, + "quote-props": 0, + "unicorn/filename-case": 0, + }, + }, +]; diff --git a/api_tests/package.json b/api_tests/package.json index d80edfdc5..6a14bded7 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -8,7 +8,7 @@ "license": "AGPL-3.0", "packageManager": "pnpm@9.4.0", "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 && prettier --check 'src/**/*.ts'", "fix": "prettier --write src && eslint --fix src", "api-test": "jest -i follow.spec.ts && jest -i image.spec.ts && jest -i user.spec.ts && jest -i private_message.spec.ts && jest -i community.spec.ts && jest -i post.spec.ts && jest -i comment.spec.ts ", "api-test-follow": "jest -i follow.spec.ts", @@ -28,9 +28,10 @@ "eslint": "^9.0.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.5.0", - "lemmy-js-client": "0.19.4", + "lemmy-js-client": "0.19.5-alpha.1", "prettier": "^3.2.5", "ts-jest": "^29.1.0", - "typescript": "^5.4.4" + "typescript": "^5.4.4", + "typescript-eslint": "^7.13.0" } } diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index de2c9e84c..31ec952c1 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -33,8 +33,8 @@ importers: specifier: ^29.5.0 version: 29.7.0(@types/node@20.14.5) lemmy-js-client: - specifier: 0.19.4 - version: 0.19.4 + specifier: 0.19.5-alpha.1 + version: 0.19.5-alpha.1 prettier: specifier: ^3.2.5 version: 3.3.2 @@ -44,6 +44,9 @@ importers: typescript: specifier: ^5.4.4 version: 5.4.5 + typescript-eslint: + specifier: ^7.13.0 + version: 7.13.0(eslint@9.5.0)(typescript@5.4.5) packages: @@ -416,6 +419,17 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + '@typescript-eslint/eslint-plugin@7.13.0': + resolution: {integrity: sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + '@typescript-eslint/parser': ^7.0.0 + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/eslint-plugin@7.13.1': resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -427,6 +441,16 @@ packages: typescript: optional: true + '@typescript-eslint/parser@7.13.0': + resolution: {integrity: sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/parser@7.13.1': resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} engines: {node: ^18.18.0 || >=20.0.0} @@ -437,10 +461,24 @@ packages: typescript: optional: true + '@typescript-eslint/scope-manager@7.13.0': + resolution: {integrity: sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==} + engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@7.13.1': resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/type-utils@7.13.0': + resolution: {integrity: sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/type-utils@7.13.1': resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} engines: {node: ^18.18.0 || >=20.0.0} @@ -451,10 +489,23 @@ packages: typescript: optional: true + '@typescript-eslint/types@7.13.0': + resolution: {integrity: sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==} + engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/types@7.13.1': resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@7.13.0': + resolution: {integrity: sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + '@typescript-eslint/typescript-estree@7.13.1': resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} engines: {node: ^18.18.0 || >=20.0.0} @@ -464,12 +515,22 @@ packages: typescript: optional: true + '@typescript-eslint/utils@7.13.0': + resolution: {integrity: sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + '@typescript-eslint/utils@7.13.1': resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 + '@typescript-eslint/visitor-keys@7.13.0': + resolution: {integrity: sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==} + engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/visitor-keys@7.13.1': resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} engines: {node: ^18.18.0 || >=20.0.0} @@ -1175,8 +1236,8 @@ packages: resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} engines: {node: '>=6'} - lemmy-js-client@0.19.4: - resolution: {integrity: sha512-k3d+YRDj3+JuuEP+nuEg27efR/e4m8oMk2BoC8jq9AnMrwSAKfsN2F2vG70Zke0amXtOclDZrCSHkIpNw99ikg==} + lemmy-js-client@0.19.5-alpha.1: + resolution: {integrity: sha512-GOhaiTQzrpwdmc3DFYemT2SmNmpuQJe2BWUms9QOzdYlkA1WZ0uu7axPE3s+T5OOxfy7K9Q2gsLe72dcVSlffw==} leven@3.1.0: resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} @@ -1548,6 +1609,16 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} + typescript-eslint@7.13.0: + resolution: {integrity: sha512-upO0AXxyBwJ4BbiC6CRgAJKtGYha2zw4m1g7TIVPSonwYEuf7vCicw3syjS1OxdDMTz96sZIXl3Jx3vWJLLKFw==} + engines: {node: ^18.18.0 || >=20.0.0} + peerDependencies: + eslint: ^8.56.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + typescript@5.4.5: resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} engines: {node: '>=14.17'} @@ -2119,6 +2190,24 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 + '@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/regexpp': 4.10.1 + '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.13.0 + '@typescript-eslint/type-utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.13.0 + eslint: 9.5.0 + graphemer: 1.4.0 + ignore: 5.3.1 + natural-compare: 1.4.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.10.1 @@ -2137,6 +2226,19 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/scope-manager': 7.13.0 + '@typescript-eslint/types': 7.13.0 + '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.13.0 + debug: 4.3.5 + eslint: 9.5.0 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/scope-manager': 7.13.1 @@ -2150,11 +2252,28 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/scope-manager@7.13.0': + dependencies: + '@typescript-eslint/types': 7.13.0 + '@typescript-eslint/visitor-keys': 7.13.0 + '@typescript-eslint/scope-manager@7.13.1': dependencies: '@typescript-eslint/types': 7.13.1 '@typescript-eslint/visitor-keys': 7.13.1 + '@typescript-eslint/type-utils@7.13.0(eslint@9.5.0)(typescript@5.4.5)': + dependencies: + '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) + '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + debug: 4.3.5 + eslint: 9.5.0 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/type-utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) @@ -2167,8 +2286,25 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/types@7.13.0': {} + '@typescript-eslint/types@7.13.1': {} + '@typescript-eslint/typescript-estree@7.13.0(typescript@5.4.5)': + dependencies: + '@typescript-eslint/types': 7.13.0 + '@typescript-eslint/visitor-keys': 7.13.0 + debug: 4.3.5 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.4 + semver: 7.6.2 + ts-api-utils: 1.3.0(typescript@5.4.5) + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/typescript-estree@7.13.1(typescript@5.4.5)': dependencies: '@typescript-eslint/types': 7.13.1 @@ -2184,6 +2320,17 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/utils@7.13.0(eslint@9.5.0)(typescript@5.4.5)': + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) + '@typescript-eslint/scope-manager': 7.13.0 + '@typescript-eslint/types': 7.13.0 + '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) + eslint: 9.5.0 + transitivePeerDependencies: + - supports-color + - typescript + '@typescript-eslint/utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) @@ -2195,6 +2342,11 @@ snapshots: - supports-color - typescript + '@typescript-eslint/visitor-keys@7.13.0': + dependencies: + '@typescript-eslint/types': 7.13.0 + eslint-visitor-keys: 3.4.3 + '@typescript-eslint/visitor-keys@7.13.1': dependencies: '@typescript-eslint/types': 7.13.1 @@ -3078,7 +3230,7 @@ snapshots: kleur@3.0.3: {} - lemmy-js-client@0.19.4: {} + lemmy-js-client@0.19.5-alpha.1: {} leven@3.1.0: {} @@ -3387,6 +3539,17 @@ snapshots: type-fest@0.21.3: {} + typescript-eslint@7.13.0(eslint@9.5.0)(typescript@5.4.5): + dependencies: + '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + eslint: 9.5.0 + optionalDependencies: + typescript: 5.4.5 + transitivePeerDependencies: + - supports-color + typescript@5.4.5: {} undici-types@5.26.5: {} diff --git a/api_tests/prepare-drone-federation-test.sh b/api_tests/prepare-drone-federation-test.sh index 31eb111c2..65c4827d9 100755 --- a/api_tests/prepare-drone-federation-test.sh +++ b/api_tests/prepare-drone-federation-test.sh @@ -15,7 +15,7 @@ export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queu # pictrs setup if [ ! -f "api_tests/pict-rs" ]; then - curl "https://git.asonix.dog/asonix/pict-rs/releases/download/v0.5.13/pict-rs-linux-amd64" -o api_tests/pict-rs + curl "https://git.asonix.dog/asonix/pict-rs/releases/download/v0.5.16/pict-rs-linux-amd64" -o api_tests/pict-rs chmod +x api_tests/pict-rs fi ./api_tests/pict-rs \ diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts index 123982e85..fe9470d18 100644 --- a/api_tests/src/image.spec.ts +++ b/api_tests/src/image.spec.ts @@ -160,6 +160,7 @@ test("Purge post, linked image removed", async () => { upload.url, ); expect(post.post_view.post.url).toBe(upload.url); + expect(post.post_view.image_details).toBeDefined(); // purge post const purgeForm: PurgePost = { @@ -184,6 +185,9 @@ test("Images in remote image post are proxied if setting enabled", async () => { const post = postRes.post_view.post; expect(post).toBeDefined(); + // Make sure it fetched the image details + expect(postRes.post_view.image_details).toBeDefined(); + // remote image gets proxied after upload expect( post.thumbnail_url?.startsWith( diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index cb45274c6..fe17bd979 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -502,7 +502,7 @@ test("Enforce site ban federation for local user", async () => { } let newAlphaUserJwt = await loginUser(alpha, alphaUserPerson.name); alphaUserHttp.setHeaders({ - Authorization: "Bearer " + newAlphaUserJwt.jwt ?? "", + Authorization: "Bearer " + newAlphaUserJwt.jwt, }); // alpha makes new post in beta community, it federates let postRes2 = await createPost(alphaUserHttp, betaCommunity!.community.id); diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index 8a423ff7c..ddbb3dd0c 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -11,7 +11,7 @@ use encoding_rs::{Encoding, UTF_8}; use lemmy_db_schema::{ newtypes::DbUrl, source::{ - images::{LocalImage, LocalImageForm}, + images::{ImageDetailsForm, LocalImage, LocalImageForm}, local_site::LocalSite, post::{Post, PostUpdateForm}, }, @@ -209,6 +209,19 @@ pub struct PictrsFileDetails { pub created_at: DateTime, } +impl PictrsFileDetails { + /// Builds the image form. This should always use the thumbnail_url, + /// Because the post_view joins to it + pub fn build_image_details_form(&self, thumbnail_url: &Url) -> ImageDetailsForm { + ImageDetailsForm { + link: thumbnail_url.clone().into(), + width: self.width.into(), + height: self.height.into(), + content_type: self.content_type.clone(), + } + } +} + #[derive(Deserialize, Serialize, Debug)] struct PictrsPurgeResponse { msg: String, @@ -316,11 +329,52 @@ async fn generate_pictrs_thumbnail(image_url: &Url, context: &LemmyContext) -> L let protocol_and_hostname = context.settings().get_protocol_and_hostname(); let thumbnail_url = image.thumbnail_url(&protocol_and_hostname)?; - LocalImage::create(&mut context.pool(), &form).await?; + // Also store the details for the image + let details_form = image.details.build_image_details_form(&thumbnail_url); + LocalImage::create(&mut context.pool(), &form, &details_form).await?; Ok(thumbnail_url) } +/// Fetches the image details for pictrs proxied images +/// +/// We don't need to check for image mode, as that's already been done +#[tracing::instrument(skip_all)] +pub async fn fetch_pictrs_proxied_image_details( + image_url: &Url, + context: &LemmyContext, +) -> LemmyResult { + let pictrs_url = context.settings().pictrs_config()?.url; + let encoded_image_url = encode(image_url.as_str()); + + // Pictrs needs you to fetch the proxied image before you can fetch the details + let proxy_url = format!("{pictrs_url}image/original?proxy={encoded_image_url}"); + + let res = context + .client() + .get(&proxy_url) + .timeout(REQWEST_TIMEOUT) + .send() + .await? + .status(); + if !res.is_success() { + Err(LemmyErrorType::NotAnImageType)? + } + + let details_url = format!("{pictrs_url}image/details/original?proxy={encoded_image_url}"); + + let res = context + .client() + .get(&details_url) + .timeout(REQWEST_TIMEOUT) + .send() + .await? + .json() + .await?; + + Ok(res) +} + // TODO: get rid of this by reading content type from db #[tracing::instrument(skip_all)] async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> LemmyResult<()> { diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index ba5756998..97b12cc5b 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -1,6 +1,10 @@ use crate::{ context::LemmyContext, - request::{delete_image_from_pictrs, purge_image_from_pictrs}, + request::{ + delete_image_from_pictrs, + fetch_pictrs_proxied_image_details, + purge_image_from_pictrs, + }, site::{FederatedInstances, InstanceWithFederationState}, }; use chrono::{DateTime, Days, Local, TimeZone, Utc}; @@ -949,7 +953,18 @@ pub async fn process_markdown( if context.settings().pictrs_config()?.image_mode() == PictrsImageMode::ProxyAllImages { let (text, links) = markdown_rewrite_image_links(text); - RemoteImage::create(&mut context.pool(), links).await?; + + // Create images and image detail rows + for link in links { + // Insert image details for the remote image + let details_res = fetch_pictrs_proxied_image_details(&link, context).await; + if let Ok(details) = details_res { + let proxied = + build_proxied_image_url(&link, &context.settings().get_protocol_and_hostname())?; + let details_form = details.build_image_details_form(&proxied); + RemoteImage::create(&mut context.pool(), &details_form).await?; + } + } Ok(text) } else { Ok(text) @@ -984,8 +999,14 @@ async fn proxy_image_link_internal( Ok(link.into()) } else if image_mode == PictrsImageMode::ProxyAllImages { let proxied = build_proxied_image_url(&link, &context.settings().get_protocol_and_hostname())?; + // This should fail softly, since pictrs might not even be running + let details_res = fetch_pictrs_proxied_image_details(&link, context).await; + + if let Ok(details) = details_res { + let details_form = details.build_image_details_form(&proxied); + RemoteImage::create(&mut context.pool(), &details_form).await?; + }; - RemoteImage::create(&mut context.pool(), vec![link]).await?; Ok(proxied.into()) } else { Ok(link.into()) @@ -1123,10 +1144,13 @@ mod tests { "https://lemmy-alpha/api/v3/image_proxy?url=http%3A%2F%2Flemmy-beta%2Fimage.png", proxied.as_str() ); + + // This fails, because the details can't be fetched without pictrs running, + // And a remote image won't be inserted. assert!( RemoteImage::validate(&mut context.pool(), remote_image.into()) .await - .is_ok() + .is_err() ); } } diff --git a/crates/db_schema/src/impls/images.rs b/crates/db_schema/src/impls/images.rs index 9589aeee3..547bfc4e2 100644 --- a/crates/db_schema/src/impls/images.rs +++ b/crates/db_schema/src/impls/images.rs @@ -1,7 +1,14 @@ use crate::{ newtypes::DbUrl, - schema::{local_image, remote_image}, - source::images::{LocalImage, LocalImageForm, RemoteImage, RemoteImageForm}, + schema::{image_details, local_image, remote_image}, + source::images::{ + ImageDetails, + ImageDetailsForm, + LocalImage, + LocalImageForm, + RemoteImage, + RemoteImageForm, + }, utils::{get_conn, DbPool}, }; use diesel::{ @@ -13,15 +20,29 @@ use diesel::{ NotFound, QueryDsl, }; -use diesel_async::RunQueryDsl; -use url::Url; +use diesel_async::{AsyncPgConnection, RunQueryDsl}; impl LocalImage { - pub async fn create(pool: &mut DbPool<'_>, form: &LocalImageForm) -> Result { + pub async fn create( + pool: &mut DbPool<'_>, + form: &LocalImageForm, + image_details_form: &ImageDetailsForm, + ) -> Result { let conn = &mut get_conn(pool).await?; - insert_into(local_image::table) - .values(form) - .get_result::(conn) + conn + .build_transaction() + .run(|conn| { + Box::pin(async move { + let local_insert = insert_into(local_image::table) + .values(form) + .get_result::(conn) + .await; + + ImageDetails::create(conn, image_details_form).await?; + + local_insert + }) as _ + }) .await } @@ -39,16 +60,26 @@ impl LocalImage { } impl RemoteImage { - pub async fn create(pool: &mut DbPool<'_>, links: Vec) -> Result { + pub async fn create(pool: &mut DbPool<'_>, form: &ImageDetailsForm) -> Result { let conn = &mut get_conn(pool).await?; - let forms = links - .into_iter() - .map(|url| RemoteImageForm { link: url.into() }) - .collect::>(); - insert_into(remote_image::table) - .values(forms) - .on_conflict_do_nothing() - .execute(conn) + conn + .build_transaction() + .run(|conn| { + Box::pin(async move { + let remote_image_form = RemoteImageForm { + link: form.link.clone(), + }; + let remote_insert = insert_into(remote_image::table) + .values(remote_image_form) + .on_conflict_do_nothing() + .execute(conn) + .await; + + ImageDetails::create(conn, form).await?; + + remote_insert + }) as _ + }) .await } @@ -67,3 +98,16 @@ impl RemoteImage { } } } + +impl ImageDetails { + pub(crate) async fn create( + conn: &mut AsyncPgConnection, + form: &ImageDetailsForm, + ) -> Result { + insert_into(image_details::table) + .values(form) + .on_conflict_do_nothing() + .execute(conn) + .await + } +} diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index 50bdac751..c3102b578 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -309,6 +309,15 @@ diesel::table! { } } +diesel::table! { + image_details (link) { + link -> Text, + width -> Int4, + height -> Int4, + content_type -> Text, + } +} + diesel::table! { instance (id) { id -> Int4, @@ -849,8 +858,7 @@ diesel::table! { } diesel::table! { - remote_image (id) { - id -> Int4, + remote_image (link) { link -> Text, published -> Timestamptz, } @@ -1055,6 +1063,7 @@ diesel::allow_tables_to_appear_in_same_query!( federation_allowlist, federation_blocklist, federation_queue_state, + image_details, instance, instance_block, language, diff --git a/crates/db_schema/src/source/images.rs b/crates/db_schema/src/source/images.rs index 9d48e011b..0dea4b84f 100644 --- a/crates/db_schema/src/source/images.rs +++ b/crates/db_schema/src/source/images.rs @@ -1,13 +1,12 @@ use crate::newtypes::{DbUrl, LocalUserId}; #[cfg(feature = "full")] -use crate::schema::{local_image, remote_image}; +use crate::schema::{image_details, local_image, remote_image}; use chrono::{DateTime, Utc}; use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; use std::fmt::Debug; #[cfg(feature = "full")] use ts_rs::TS; -use typed_builder::TypedBuilder; #[skip_serializing_none] #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -30,7 +29,7 @@ pub struct LocalImage { pub published: DateTime, } -#[derive(Debug, Clone, TypedBuilder)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = local_image))] pub struct LocalImageForm { @@ -46,15 +45,39 @@ pub struct LocalImageForm { #[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable))] #[cfg_attr(feature = "full", diesel(table_name = remote_image))] #[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] +#[cfg_attr(feature = "full", diesel(primary_key(link)))] pub struct RemoteImage { - pub id: i32, pub link: DbUrl, pub published: DateTime, } -#[derive(Debug, Clone, TypedBuilder)] +#[derive(Debug, Clone)] #[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] #[cfg_attr(feature = "full", diesel(table_name = remote_image))] pub struct RemoteImageForm { pub link: DbUrl, } + +#[skip_serializing_none] +#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] +#[cfg_attr(feature = "full", derive(Queryable, Selectable, Identifiable, TS))] +#[cfg_attr(feature = "full", ts(export))] +#[cfg_attr(feature = "full", diesel(table_name = image_details))] +#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))] +#[cfg_attr(feature = "full", diesel(primary_key(link)))] +pub struct ImageDetails { + pub link: DbUrl, + pub width: i32, + pub height: i32, + pub content_type: String, +} + +#[derive(Debug, Clone)] +#[cfg_attr(feature = "full", derive(Insertable, AsChangeset))] +#[cfg_attr(feature = "full", diesel(table_name = image_details))] +pub struct ImageDetailsForm { + pub link: DbUrl, + pub width: i32, + pub height: i32, + pub content_type: String, +} diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index fb616b0d3..d472fc604 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -28,6 +28,7 @@ use lemmy_db_schema::{ community_follower, community_moderator, community_person_ban, + image_details, instance_block, local_user, local_user_language, @@ -218,6 +219,7 @@ fn queries<'a>() -> Queries< .inner_join(person::table) .inner_join(community::table) .inner_join(post::table) + .left_join(image_details::table.on(post::thumbnail_url.eq(image_details::link.nullable()))) .left_join( post_saved::table.on( post_aggregates::post_id @@ -229,6 +231,7 @@ fn queries<'a>() -> Queries< post::all_columns, person::all_columns, community::all_columns, + image_details::all_columns.nullable(), is_creator_banned_from_community, is_local_user_banned_from_community_selection, creator_is_moderator, @@ -1631,6 +1634,7 @@ mod tests { public_key: inserted_person.public_key.clone(), last_refreshed_at: inserted_person.last_refreshed_at, }, + image_details: None, creator_banned_from_community: false, banned_from_community: false, creator_is_moderator: false, diff --git a/crates/db_views/src/structs.rs b/crates/db_views/src/structs.rs index 350e4cad4..3c219d63f 100644 --- a/crates/db_views/src/structs.rs +++ b/crates/db_views/src/structs.rs @@ -8,7 +8,7 @@ use lemmy_db_schema::{ community::Community, custom_emoji::CustomEmoji, custom_emoji_keyword::CustomEmojiKeyword, - images::LocalImage, + images::{ImageDetails, LocalImage}, local_site::LocalSite, local_site_rate_limit::LocalSiteRateLimit, local_user::LocalUser, @@ -131,6 +131,7 @@ pub struct PostView { pub post: Post, pub creator: Person, pub community: Community, + pub image_details: Option, pub creator_banned_from_community: bool, pub banned_from_community: bool, pub creator_is_moderator: bool, diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs index 96d7d317c..049bd6cc8 100644 --- a/crates/routes/src/images.rs +++ b/crates/routes/src/images.rs @@ -103,7 +103,13 @@ async fn upload( pictrs_alias: image.file.to_string(), pictrs_delete_token: image.delete_token.to_string(), }; - LocalImage::create(&mut context.pool(), &form).await?; + + let protocol_and_hostname = context.settings().get_protocol_and_hostname(); + let thumbnail_url = image.thumbnail_url(&protocol_and_hostname)?; + + // Also store the details for the image + let details_form = image.details.build_image_details_form(&thumbnail_url); + LocalImage::create(&mut context.pool(), &form, &details_form).await?; } } diff --git a/migrations/2024-05-05-162540_add_image_detail_table/down.sql b/migrations/2024-05-05-162540_add_image_detail_table/down.sql new file mode 100644 index 000000000..819277c7f --- /dev/null +++ b/migrations/2024-05-05-162540_add_image_detail_table/down.sql @@ -0,0 +1,7 @@ +ALTER TABLE remote_image + ADD UNIQUE (link), + DROP CONSTRAINT remote_image_pkey, + ADD COLUMN id serial PRIMARY KEY; + +DROP TABLE image_details; + diff --git a/migrations/2024-05-05-162540_add_image_detail_table/up.sql b/migrations/2024-05-05-162540_add_image_detail_table/up.sql new file mode 100644 index 000000000..9b2ed9658 --- /dev/null +++ b/migrations/2024-05-05-162540_add_image_detail_table/up.sql @@ -0,0 +1,15 @@ +-- Drop the id column from the remote_image table, just use link +ALTER TABLE remote_image + DROP COLUMN id, + ADD PRIMARY KEY (link), + DROP CONSTRAINT remote_image_link_key; + +-- No good way to do references here unfortunately, unless we combine the images tables +-- The link should be the URL, not the pictrs_alias, to allow joining from post.thumbnail_url +CREATE TABLE image_details ( + link text PRIMARY KEY, + width integer NOT NULL, + height integer NOT NULL, + content_type text NOT NULL +); + From 36e6f7ec78fdddb3a0427a0480fa2f689bed845f Mon Sep 17 00:00:00 2001 From: dullbananas Date: Fri, 21 Jun 2024 10:44:55 -0700 Subject: [PATCH 02/69] Fix order in `CommunityModeratorView::get_community_first_mods` (#4859) * Fix order in `CommunityModeratorView::get_community_first_mods` * Update community_moderator_view.rs * Update community_moderator_view.rs --- crates/db_views_actor/src/community_moderator_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index 808fc0340..f58e3fee0 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -90,7 +90,7 @@ impl CommunityModeratorView { .distinct_on(community_moderator::community_id) .order_by(( community_moderator::community_id, - community_moderator::person_id, + community_moderator::published, )) .load::(conn) .await From c8d155102a8065d6c77afc537cff7126c546f99e Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 21 Jun 2024 17:38:44 -0400 Subject: [PATCH 03/69] Removing renovate from git cliff (#4858) * Removing renovate from git cliff * Formatting. --- cliff.toml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cliff.toml b/cliff.toml index d8975a171..b5b8c3f16 100644 --- a/cliff.toml +++ b/cliff.toml @@ -26,6 +26,7 @@ body = """ {%- endif %} {%- endfor -%} +{%- if github -%} {% if github.contributors | filter(attribute="is_first_time", value=true) | length != 0 %} {% raw %}\n{% endraw -%} ## New Contributors @@ -36,6 +37,7 @@ body = """ [#{{ contributor.pr_number }}]({{ self::remote_url() }}/pull/{{ contributor.pr_number }}) \ {%- endif %} {%- endfor -%} +{%- endif -%} {% if version %} {% if previous.version %} @@ -70,6 +72,7 @@ commit_preprocessors = [ # remove issue numbers from commits { pattern = '\((\w+\s)?#([0-9]+)\)', replace = "" }, ] +commit_parsers = [{ field = "author.name", pattern = "renovate", skip = true }] # protect breaking changes from being skipped due to matching a skipping commit_parser protect_breaking_commits = false # filter out the commits that are not matched by commit parsers From d09854a7220d9585d10977f1aff7326032014a6c Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 21 Jun 2024 17:39:40 -0400 Subject: [PATCH 04/69] Adding a show_read override to GetPosts. (#4846) * Adding a show_read override to GetPosts. - If show_read is true, it overrides the local user show_read setting. - Fixes #4124 * Addressing PR comments. * Update crates/db_views/src/post_view.rs Co-authored-by: dullbananas * Fixing formatting. --------- Co-authored-by: dullbananas --- crates/api_common/src/post.rs | 2 + crates/apub/src/api/list_comments.rs | 8 ++-- crates/apub/src/api/list_posts.rs | 12 +++--- crates/apub/src/api/read_person.rs | 4 +- crates/db_views/src/comment_view.rs | 22 +++++------ crates/db_views/src/post_view.rs | 56 ++++++++++++++++++++-------- 6 files changed, 66 insertions(+), 38 deletions(-) diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index 3d1bc4078..f42a468b5 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -79,6 +79,8 @@ pub struct GetPosts { pub liked_only: Option, pub disliked_only: Option, pub show_hidden: Option, + /// If true, then show the read posts (even if your user setting is to hide them) + pub show_read: Option, pub page_cursor: Option, } diff --git a/crates/apub/src/api/list_comments.rs b/crates/apub/src/api/list_comments.rs index d83b9a135..12d18110e 100644 --- a/crates/apub/src/api/list_comments.rs +++ b/crates/apub/src/api/list_comments.rs @@ -37,11 +37,11 @@ pub async fn list_comments( }; let sort = data.sort; let max_depth = data.max_depth; - let saved_only = data.saved_only.unwrap_or_default(); + let saved_only = data.saved_only; - let liked_only = data.liked_only.unwrap_or_default(); - let disliked_only = data.disliked_only.unwrap_or_default(); - if liked_only && disliked_only { + let liked_only = data.liked_only; + let disliked_only = data.disliked_only; + if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() { return Err(LemmyError::from(LemmyErrorType::ContradictingFilters)); } diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index 31bdd0c8e..c00c87f4c 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -40,12 +40,13 @@ pub async fn list_posts( } else { data.community_id }; - let saved_only = data.saved_only.unwrap_or_default(); - let show_hidden = data.show_hidden.unwrap_or_default(); + let saved_only = data.saved_only; + let show_hidden = data.show_hidden; + let show_read = data.show_read; - let liked_only = data.liked_only.unwrap_or_default(); - let disliked_only = data.disliked_only.unwrap_or_default(); - if liked_only && disliked_only { + let liked_only = data.liked_only; + let disliked_only = data.disliked_only; + if liked_only.unwrap_or_default() && disliked_only.unwrap_or_default() { return Err(LemmyError::from(LemmyErrorType::ContradictingFilters)); } @@ -82,6 +83,7 @@ pub async fn list_posts( page_after, limit, show_hidden, + show_read, ..Default::default() } .list(&local_site.site, &mut context.pool()) diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index a6b3560aa..149e06a17 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -55,11 +55,11 @@ pub async fn read_person( let sort = data.sort; let page = data.page; let limit = data.limit; - let saved_only = data.saved_only.unwrap_or_default(); + let saved_only = data.saved_only; 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 { + let creator_id = if !saved_only.unwrap_or_default() { Some(person_details_id) } else { None diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 61dbceb4b..cd7560a00 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -252,7 +252,7 @@ fn queries<'a>() -> Queries< } // If its saved only, then filter, and order by the saved time, not the comment creation time. - if options.saved_only { + if options.saved_only.unwrap_or_default() { query = query .filter(comment_saved::person_id.is_not_null()) .then_order_by(comment_saved::published.desc()); @@ -260,9 +260,9 @@ fn queries<'a>() -> Queries< if let Some(my_id) = options.local_user.person_id() { let not_creator_filter = comment::creator_id.ne(my_id); - if options.liked_only { + if options.liked_only.unwrap_or_default() { query = query.filter(not_creator_filter).filter(score(my_id).eq(1)); - } else if options.disliked_only { + } else if options.disliked_only.unwrap_or_default() { query = query.filter(not_creator_filter).filter(score(my_id).eq(-1)); } } @@ -398,9 +398,9 @@ pub struct CommentQuery<'a> { pub creator_id: Option, pub local_user: Option<&'a LocalUser>, pub search_term: Option, - pub saved_only: bool, - pub liked_only: bool, - pub disliked_only: bool, + pub saved_only: Option, + pub liked_only: Option, + pub disliked_only: Option, pub page: Option, pub limit: Option, pub max_depth: Option, @@ -711,8 +711,8 @@ mod tests { CommentLike::like(pool, &comment_like_form).await?; let read_liked_comment_views = CommentQuery { - local_user: (Some(&data.timmy_local_user_view.local_user)), - liked_only: (true), + local_user: Some(&data.timmy_local_user_view.local_user), + liked_only: Some(true), ..Default::default() } .list(pool) @@ -727,8 +727,8 @@ mod tests { assert_length!(1, read_liked_comment_views); let read_disliked_comment_views: Vec = CommentQuery { - local_user: (Some(&data.timmy_local_user_view.local_user)), - disliked_only: (true), + local_user: Some(&data.timmy_local_user_view.local_user), + disliked_only: Some(true), ..Default::default() } .list(pool) @@ -980,7 +980,7 @@ mod tests { // Fetch the saved comments let comments = CommentQuery { local_user: Some(&data.timmy_local_user_view.local_user), - saved_only: true, + saved_only: Some(true), ..Default::default() } .list(pool) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index d472fc604..0e22f689b 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -403,14 +403,17 @@ fn queries<'a>() -> Queries< }; // If its saved only, then filter, and order by the saved time, not the comment creation time. - if options.saved_only { + if options.saved_only.unwrap_or_default() { query = query .filter(post_saved::person_id.is_not_null()) .then_order_by(post_saved::published.desc()); } // Only hide the read posts, if the saved_only is false. Otherwise ppl with the hide_read // setting wont be able to see saved posts. - else if !options.local_user.show_read_posts() { + else if !options + .show_read + .unwrap_or(options.local_user.show_read_posts()) + { // Do not hide read posts when it is a user profile view // Or, only hide read posts on non-profile views if let (None, Some(person_id)) = (options.creator_id, options.local_user.person_id()) { @@ -418,7 +421,7 @@ fn queries<'a>() -> Queries< } } - if !options.show_hidden { + if !options.show_hidden.unwrap_or_default() { // If a creator id isn't given (IE its on home or community pages), hide the hidden posts if let (None, Some(person_id)) = (options.creator_id, options.local_user.person_id()) { query = query.filter(not(is_hidden(person_id))); @@ -427,9 +430,9 @@ fn queries<'a>() -> Queries< if let Some(my_id) = options.local_user.person_id() { let not_creator_filter = post_aggregates::creator_id.ne(my_id); - if options.liked_only { + if options.liked_only.unwrap_or_default() { query = query.filter(not_creator_filter).filter(score(my_id).eq(1)); - } else if options.disliked_only { + } else if options.disliked_only.unwrap_or_default() { query = query.filter(not_creator_filter).filter(score(my_id).eq(-1)); } }; @@ -476,7 +479,7 @@ fn queries<'a>() -> Queries< let page_after = options.page_after.map(|c| c.0); let page_before_or_equal = options.page_before_or_equal.map(|c| c.0); - if options.page_back { + if options.page_back.unwrap_or_default() { query = query .before(page_after) .after_or_equal(page_before_or_equal) @@ -604,15 +607,16 @@ pub struct PostQuery<'a> { pub local_user: Option<&'a LocalUser>, pub search_term: Option, pub url_search: Option, - pub saved_only: bool, - pub liked_only: bool, - pub disliked_only: bool, + pub saved_only: Option, + pub liked_only: Option, + pub disliked_only: Option, pub page: Option, pub limit: Option, pub page_after: Option, pub page_before_or_equal: Option, - pub page_back: bool, - pub show_hidden: bool, + pub page_back: Option, + pub show_hidden: Option, + pub show_read: Option, } impl<'a> PostQuery<'a> { @@ -683,7 +687,7 @@ impl<'a> PostQuery<'a> { if (v.len() as i64) < limit { Ok(Some(self.clone())) } else { - let item = if self.page_back { + let item = if self.page_back.unwrap_or_default() { // for backward pagination, get first element instead v.into_iter().next() } else { @@ -1122,7 +1126,7 @@ mod tests { // Read the liked only let read_liked_post_listing = PostQuery { community_id: Some(data.inserted_community.id), - liked_only: true, + liked_only: Some(true), ..data.default_post_query() } .list(&data.site, pool) @@ -1133,7 +1137,7 @@ mod tests { let read_disliked_post_listing = PostQuery { community_id: Some(data.inserted_community.id), - disliked_only: true, + disliked_only: Some(true), ..data.default_post_query() } .list(&data.site, pool) @@ -1459,7 +1463,7 @@ mod tests { loop { let post_listings = PostQuery { page_after: page_before, - page_back: true, + page_back: Some(true), ..options.clone() } .list(&data.site, pool) @@ -1517,6 +1521,26 @@ mod tests { let post_listings_hide_read = data.default_post_query().list(&data.site, pool).await?; assert_eq!(vec![POST], names(&post_listings_hide_read)); + // Test with the show_read override as true + let post_listings_show_read_true = PostQuery { + show_read: Some(true), + ..data.default_post_query() + } + .list(&data.site, pool) + .await?; + assert_eq!( + vec![POST_BY_BOT, POST], + names(&post_listings_show_read_true) + ); + + // Test with the show_read override as false + let post_listings_show_read_false = PostQuery { + show_read: Some(false), + ..data.default_post_query() + } + .list(&data.site, pool) + .await?; + assert_eq!(vec![POST], names(&post_listings_show_read_false)); cleanup(data, pool).await } @@ -1543,7 +1567,7 @@ mod tests { let post_listings_show_hidden = PostQuery { sort: Some(SortType::New), local_user: Some(&data.local_user_view.local_user), - show_hidden: true, + show_hidden: Some(true), ..Default::default() } .list(&data.site, pool) From 91202073142013b70c17a6bfe3b6ea71a8cde670 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Wed, 26 Jun 2024 01:47:09 -0700 Subject: [PATCH 05/69] Format replaceable_schema files in lint.sh (#4868) --- scripts/lint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lint.sh b/scripts/lint.sh index 7a93b5f54..20d89acb4 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -12,6 +12,6 @@ cargo +nightly fmt taplo format # Format sql files -find migrations -type f -name '*.sql' -exec pg_format -i {} + +find migrations crates/db_schema/replaceable_schema -type f -name '*.sql' -exec pg_format -i {} + cargo clippy --workspace --fix --allow-staged --allow-dirty --tests --all-targets --all-features -- -D warnings From 2c57f420224fb5c7bbcb35dd5cddb40b08c00e13 Mon Sep 17 00:00:00 2001 From: Richard Schwab Date: Tue, 2 Jul 2024 15:30:13 +0200 Subject: [PATCH 06/69] Relax timeout for sending activities (#4864) * Relax timeout for sending activities Lemmy considers timeouts during activity sending as retryable errors. While it is frequently enough to retry sending the same activity again after the original submission attempt resulted in a timeout, allowing the receiving side to use more time for synchronous processing should reduce the number of retries needed overall and improve overall compatibility. Some ActivityPub software, such as Mastodon, implements a queue for processing received activities asynchronously, which allows immediately returning a response for activity submissions. Other software, such as Lemmy or Hubzilla implement synchronous processing of activities before returning a response. ActivityPub does not specify specific timeouts to be used: https://github.com/w3c/activitypub/issues/365 * Simplify usage of federation_sender_config Option --- src/lib.rs | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 26740a444..74c05deaa 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -55,7 +55,7 @@ use prometheus_metrics::serve_prometheus; use reqwest_middleware::ClientBuilder; use reqwest_tracing::TracingMiddleware; use serde_json::json; -use std::{env, ops::Deref}; +use std::{env, ops::Deref, time::Duration}; use tokio::signal::unix::SignalKind; use tracing::subscriber::set_global_default; use tracing_actix_web::TracingLogger; @@ -64,6 +64,13 @@ use tracing_log::LogTracer; use tracing_subscriber::{filter::Targets, layer::SubscriberExt, Layer, Registry}; use url::Url; +/// Timeout for HTTP requests while sending activities. A longer timeout provides better +/// compatibility with other ActivityPub software that might allocate more time for synchronous +/// processing of incoming activities. This timeout should be slightly longer than the time we +/// expect a remote server to wait before aborting processing on its own to account for delays from +/// establishing the HTTP connection and sending the request itself. +const ACTIVITY_SENDING_TIMEOUT: Duration = Duration::from_secs(125); + #[derive(Parser, Debug)] #[command( version, @@ -173,8 +180,8 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> { serve_prometheus(prometheus, context.clone())?; } - let mut federation_config = FederationConfig::builder(); - federation_config + let mut federation_config_builder = FederationConfig::builder(); + federation_config_builder .domain(SETTINGS.hostname.clone()) .app_data(context.clone()) .client(client.clone()) @@ -184,9 +191,9 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> { .url_verifier(Box::new(VerifyUrlData(context.inner_pool().clone()))); if local_site.federation_signed_fetch { let site: ApubSite = site_view.site.into(); - federation_config.signed_fetch_actor(&site); + federation_config_builder.signed_fetch_actor(&site); } - let federation_config = federation_config.build().await?; + let federation_config = federation_config_builder.build().await?; MATCH_OUTGOING_ACTIVITIES .set(Box::new(move |d, c| { @@ -209,13 +216,23 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> { } else { None }; - let federate = (!args.disable_activity_sending).then(|| { + + // This FederationConfig instance is exclusively used to send activities, so we can safely + // increase the timeout without affecting timeouts for resolving objects anywhere. + let federation_sender_config = if !args.disable_activity_sending { + let mut federation_sender_config = federation_config_builder.clone(); + federation_sender_config.request_timeout(ACTIVITY_SENDING_TIMEOUT); + Some(federation_sender_config.build().await?) + } else { + None + }; + let federate = federation_sender_config.map(|cfg| { SendManager::run( Opts { process_index: args.federate_process_index, process_count: args.federate_process_count, }, - federation_config, + cfg, ) }); let mut interrupt = tokio::signal::unix::signal(SignalKind::interrupt())?; From d90e8f8550c24c0c9e4ef2a4c370dcd73a4511fe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 09:37:37 -0400 Subject: [PATCH 07/69] Update Rust crate clap to v4.5.8 (#4876) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a14147e09..fef5f8c3f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -977,9 +977,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5db83dced34638ad474f39f250d7fea9598bdd239eaced1bdf45d597da0f433f" +checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" dependencies = [ "clap_builder", "clap_derive", @@ -987,9 +987,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.7" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7e204572485eb3fbf28f871612191521df159bc3e15a9f5064c66dba3a8c05f" +checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" dependencies = [ "anstream", "anstyle", @@ -999,9 +999,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.5" +version = "4.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c780290ccf4fb26629baa7a1081e68ced113f1d3ec302fa5948f1c381ebf06c6" +checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3281,7 +3281,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.48.5", ] [[package]] From a7c39226e2bc05d7ab13da94bc8ddc1a6c9c5419 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 2 Jul 2024 09:39:37 -0400 Subject: [PATCH 08/69] Remove unused PersonBlockId. (#4880) - Fixes #4879 --- crates/db_schema/src/newtypes.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/crates/db_schema/src/newtypes.rs b/crates/db_schema/src/newtypes.rs index 10abfaec4..c5c9e8e84 100644 --- a/crates/db_schema/src/newtypes.rs +++ b/crates/db_schema/src/newtypes.rs @@ -85,12 +85,6 @@ impl fmt::Display for PrivateMessageId { /// The person mention id. pub struct PersonMentionId(i32); -#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] -#[cfg_attr(feature = "full", derive(DieselNewType, TS))] -#[cfg_attr(feature = "full", ts(export))] -/// The person block id. -pub struct PersonBlockId(i32); - #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] #[cfg_attr(feature = "full", derive(DieselNewType, TS))] #[cfg_attr(feature = "full", ts(export))] From fd58b4f8096fa9006fe4420878631411c99953fb Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 2 Jul 2024 06:40:18 -0700 Subject: [PATCH 09/69] Exponential controversy rank (#4872) * Update utils.sql * add migration --- crates/db_schema/replaceable_schema/utils.sql | 2 +- .../down.sql | 17 +++++++++++++++++ .../up.sql | 17 +++++++++++++++++ 3 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 migrations/2024-07-01-014711_exponential_controversy/down.sql create mode 100644 migrations/2024-07-01-014711_exponential_controversy/up.sql diff --git a/crates/db_schema/replaceable_schema/utils.sql b/crates/db_schema/replaceable_schema/utils.sql index f236c5387..26447f2c2 100644 --- a/crates/db_schema/replaceable_schema/utils.sql +++ b/crates/db_schema/replaceable_schema/utils.sql @@ -8,7 +8,7 @@ CREATE FUNCTION r.controversy_rank (upvotes numeric, downvotes numeric) 0 ELSE ( - upvotes + downvotes) * CASE WHEN upvotes > downvotes THEN + upvotes + downvotes) ^ CASE WHEN upvotes > downvotes THEN downvotes::float / upvotes::float ELSE upvotes::float / downvotes::float diff --git a/migrations/2024-07-01-014711_exponential_controversy/down.sql b/migrations/2024-07-01-014711_exponential_controversy/down.sql new file mode 100644 index 000000000..15a7f296a --- /dev/null +++ b/migrations/2024-07-01-014711_exponential_controversy/down.sql @@ -0,0 +1,17 @@ +UPDATE + post_aggregates +SET + controversy_rank = CASE WHEN downvotes <= 0 + OR upvotes <= 0 THEN + 0 + ELSE + (upvotes + downvotes) * CASE WHEN upvotes > downvotes THEN + downvotes::float / upvotes::float + ELSE + upvotes::float / downvotes::float + END + END +WHERE + upvotes > 0 + AND downvotes > 0; + diff --git a/migrations/2024-07-01-014711_exponential_controversy/up.sql b/migrations/2024-07-01-014711_exponential_controversy/up.sql new file mode 100644 index 000000000..87a700de3 --- /dev/null +++ b/migrations/2024-07-01-014711_exponential_controversy/up.sql @@ -0,0 +1,17 @@ +UPDATE + post_aggregates +SET + controversy_rank = CASE WHEN downvotes <= 0 + OR upvotes <= 0 THEN + 0 + ELSE + (upvotes + downvotes) ^ CASE WHEN upvotes > downvotes THEN + downvotes::float / upvotes::float + ELSE + upvotes::float / downvotes::float + END + END +WHERE + upvotes > 0 + AND downvotes > 0; + From 117a8b42c8798c3de9b7015bda1b9afd9f5aa9e2 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 2 Jul 2024 10:02:32 -0400 Subject: [PATCH 10/69] Update Rust crate serde_json to v1.0.120 (#4877) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fef5f8c3f..e02388f0c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5205,9 +5205,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.117" +version = "1.0.120" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "455182ea6142b14f93f4bc5320a2b31c1f266b66a4a5c858b013302a5d8cbfc3" +checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" dependencies = [ "indexmap 2.2.6", "itoa", From 78702b59fd56f767f3d5612bfd60e294979f91f8 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Tue, 2 Jul 2024 08:23:21 -0700 Subject: [PATCH 11/69] Use trigger to generate apub URL in insert instead of update, and fix query planner options not being set when TLS is disabled (#4797) * Update create.rs * Update utils.rs * Update utils.sql * Update triggers.sql * Update utils.sql * Update create.rs * Update create.rs * Update create.rs * Update create.rs * Update create.rs * Update create.rs * Update create.rs * Update create.rs * Create up.sql * Update up.sql * Update triggers.sql * Update utils.rs * stuff * stuff * revert some changed files * Revert "revert some changed files" This reverts commit 028eabb4bdcf9eda65e0f315ca1c98f8765f9d7e. * revert the correct files * partial reverts * migration, tests, fix establish_connection * lint * pg_format --- crates/api_crud/src/comment/create.rs | 24 +---- crates/api_crud/src/post/create.rs | 28 +----- crates/api_crud/src/private_message/create.rs | 22 +---- .../db_schema/replaceable_schema/triggers.sql | 40 ++++++++ crates/db_schema/replaceable_schema/utils.sql | 7 ++ crates/db_schema/src/impls/comment.rs | 8 +- crates/db_schema/src/impls/post.rs | 5 +- crates/db_schema/src/impls/private_message.rs | 8 +- crates/db_schema/src/utils.rs | 91 +++++++++++-------- .../2024-06-24-000000_ap_id_triggers/down.sql | 9 ++ .../2024-06-24-000000_ap_id_triggers/up.sql | 9 ++ 11 files changed, 142 insertions(+), 109 deletions(-) create mode 100644 migrations/2024-06-24-000000_ap_id_triggers/down.sql create mode 100644 migrations/2024-06-24-000000_ap_id_triggers/up.sql diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index 636f83392..ff3efd946 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -8,20 +8,18 @@ use lemmy_api_common::{ utils::{ check_community_user_action, check_post_deleted_or_removed, - generate_local_apub_endpoint, get_url_blocklist, is_mod_or_admin, local_site_to_slur_regex, process_markdown, update_read_comments, - EndpointType, }, }; use lemmy_db_schema::{ impls::actor_language::default_post_language, source::{ actor_language::CommunityLanguage, - comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm, CommentUpdateForm}, + comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm}, comment_reply::{CommentReply, CommentReplyUpdateForm}, local_site::LocalSite, person_mention::{PersonMention, PersonMentionUpdateForm}, @@ -126,25 +124,7 @@ pub async fn create_comment( .await .with_lemmy_type(LemmyErrorType::CouldntCreateComment)?; - // Necessary to update the ap_id let inserted_comment_id = inserted_comment.id; - let protocol_and_hostname = context.settings().get_protocol_and_hostname(); - - let apub_id = generate_local_apub_endpoint( - EndpointType::Comment, - &inserted_comment_id.to_string(), - &protocol_and_hostname, - )?; - let updated_comment = Comment::update( - &mut context.pool(), - inserted_comment_id, - &CommentUpdateForm { - ap_id: Some(apub_id), - ..Default::default() - }, - ) - .await - .with_lemmy_type(LemmyErrorType::CouldntCreateComment)?; // Scan the comment for user mentions, add those rows let mentions = scrape_text_for_mentions(&content); @@ -170,7 +150,7 @@ pub async fn create_comment( .with_lemmy_type(LemmyErrorType::CouldntLikeComment)?; ActivityChannel::submit_activity( - SendActivityData::CreateComment(updated_comment.clone()), + SendActivityData::CreateComment(inserted_comment.clone()), &context, ) .await?; diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 0b0fad5dc..39ef8ce09 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -8,13 +8,11 @@ use lemmy_api_common::{ send_activity::SendActivityData, utils::{ check_community_user_action, - generate_local_apub_endpoint, get_url_blocklist, honeypot_check, local_site_to_slur_regex, mark_post_as_read, process_markdown_opt, - EndpointType, }, }; use lemmy_db_schema::{ @@ -23,7 +21,7 @@ use lemmy_db_schema::{ actor_language::CommunityLanguage, community::Community, local_site::LocalSite, - post::{Post, PostInsertForm, PostLike, PostLikeForm, PostUpdateForm}, + post::{Post, PostInsertForm, PostLike, PostLikeForm}, }, traits::{Crud, Likeable}, utils::diesel_url_create, @@ -147,26 +145,8 @@ pub async fn create_post( .await .with_lemmy_type(LemmyErrorType::CouldntCreatePost)?; - let inserted_post_id = inserted_post.id; - let protocol_and_hostname = context.settings().get_protocol_and_hostname(); - let apub_id = generate_local_apub_endpoint( - EndpointType::Post, - &inserted_post_id.to_string(), - &protocol_and_hostname, - )?; - let updated_post = Post::update( - &mut context.pool(), - inserted_post_id, - &PostUpdateForm { - ap_id: Some(apub_id), - ..Default::default() - }, - ) - .await - .with_lemmy_type(LemmyErrorType::CouldntCreatePost)?; - generate_post_link_metadata( - updated_post.clone(), + inserted_post.clone(), custom_thumbnail.map(Into::into), |post| Some(SendActivityData::CreatePost(post)), Some(local_site), @@ -189,11 +169,11 @@ pub async fn create_post( mark_post_as_read(person_id, post_id, &mut context.pool()).await?; - if let Some(url) = updated_post.url.clone() { + if let Some(url) = inserted_post.url.clone() { if community.visibility == CommunityVisibility::Public { spawn_try_task(async move { let mut webmention = - Webmention::new::(updated_post.ap_id.clone().into(), url.clone().into())?; + Webmention::new::(inserted_post.ap_id.clone().into(), url.clone().into())?; webmention.set_checked(true); match webmention .send() diff --git a/crates/api_crud/src/private_message/create.rs b/crates/api_crud/src/private_message/create.rs index 0381d196c..46908da6e 100644 --- a/crates/api_crud/src/private_message/create.rs +++ b/crates/api_crud/src/private_message/create.rs @@ -6,19 +6,17 @@ use lemmy_api_common::{ send_activity::{ActivityChannel, SendActivityData}, utils::{ check_person_block, - generate_local_apub_endpoint, get_interface_language, get_url_blocklist, local_site_to_slur_regex, process_markdown, send_email_to_user, - EndpointType, }, }; use lemmy_db_schema::{ source::{ local_site::LocalSite, - private_message::{PrivateMessage, PrivateMessageInsertForm, PrivateMessageUpdateForm}, + private_message::{PrivateMessage, PrivateMessageInsertForm}, }, traits::Crud, }; @@ -58,24 +56,6 @@ pub async fn create_private_message( .await .with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?; - let inserted_private_message_id = inserted_private_message.id; - let protocol_and_hostname = context.settings().get_protocol_and_hostname(); - let apub_id = generate_local_apub_endpoint( - EndpointType::PrivateMessage, - &inserted_private_message_id.to_string(), - &protocol_and_hostname, - )?; - PrivateMessage::update( - &mut context.pool(), - inserted_private_message.id, - &PrivateMessageUpdateForm { - ap_id: Some(apub_id), - ..Default::default() - }, - ) - .await - .with_lemmy_type(LemmyErrorType::CouldntCreatePrivateMessage)?; - let view = PrivateMessageView::read(&mut context.pool(), inserted_private_message.id) .await? .ok_or(LemmyErrorType::CouldntFindPrivateMessage)?; diff --git a/crates/db_schema/replaceable_schema/triggers.sql b/crates/db_schema/replaceable_schema/triggers.sql index 87866e89c..973d3325f 100644 --- a/crates/db_schema/replaceable_schema/triggers.sql +++ b/crates/db_schema/replaceable_schema/triggers.sql @@ -564,6 +564,10 @@ BEGIN IF NOT (NEW.path ~ ('*.' || id)::lquery) THEN NEW.path = NEW.path || id; END IF; + -- Set local ap_id + IF NEW.local THEN + NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/comment/' || id)); + END IF; RETURN NEW; END $$; @@ -573,3 +577,39 @@ CREATE TRIGGER change_values FOR EACH ROW EXECUTE FUNCTION r.comment_change_values (); +CREATE FUNCTION r.post_change_values () + RETURNS TRIGGER + LANGUAGE plpgsql + AS $$ +BEGIN + -- Set local ap_id + IF NEW.local THEN + NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/post/' || NEW.id::text)); + END IF; + RETURN NEW; +END +$$; + +CREATE TRIGGER change_values + BEFORE INSERT ON post + FOR EACH ROW + EXECUTE FUNCTION r.post_change_values (); + +CREATE FUNCTION r.private_message_change_values () + RETURNS TRIGGER + LANGUAGE plpgsql + AS $$ +BEGIN + -- Set local ap_id + IF NEW.local THEN + NEW.ap_id = coalesce(NEW.ap_id, r.local_url ('/private_message/' || NEW.id::text)); + END IF; + RETURN NEW; +END +$$; + +CREATE TRIGGER change_values + BEFORE INSERT ON private_message + FOR EACH ROW + EXECUTE FUNCTION r.private_message_change_values (); + diff --git a/crates/db_schema/replaceable_schema/utils.sql b/crates/db_schema/replaceable_schema/utils.sql index 26447f2c2..c766d25f2 100644 --- a/crates/db_schema/replaceable_schema/utils.sql +++ b/crates/db_schema/replaceable_schema/utils.sql @@ -57,6 +57,13 @@ BEGIN END; $$; +CREATE FUNCTION r.local_url (url_path text) + RETURNS text + LANGUAGE sql + STABLE PARALLEL SAFE RETURN ( +current_setting('lemmy.protocol_and_hostname') || url_path +); + -- This function creates statement-level triggers for all operation types. It's designed this way -- because of these limitations: -- * A trigger that uses transition tables can only handle 1 operation type. diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index 0ffd53f86..aa7b418fe 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -223,6 +223,7 @@ mod tests { use diesel_ltree::Ltree; use pretty_assertions::assert_eq; use serial_test::serial; + use url::Url; #[tokio::test] #[serial] @@ -273,7 +274,12 @@ mod tests { path: Ltree(format!("0.{}", inserted_comment.id)), published: inserted_comment.published, updated: None, - ap_id: inserted_comment.ap_id.clone(), + ap_id: Url::parse(&format!( + "https://lemmy-alpha/comment/{}", + inserted_comment.id + )) + .unwrap() + .into(), distinguished: false, local: true, language_id: LanguageId::default(), diff --git a/crates/db_schema/src/impls/post.rs b/crates/db_schema/src/impls/post.rs index ac6cf76aa..8e14bee9f 100644 --- a/crates/db_schema/src/impls/post.rs +++ b/crates/db_schema/src/impls/post.rs @@ -390,6 +390,7 @@ mod tests { use pretty_assertions::assert_eq; use serial_test::serial; use std::collections::HashSet; + use url::Url; #[tokio::test] #[serial] @@ -447,7 +448,9 @@ mod tests { embed_description: None, embed_video_url: None, thumbnail_url: None, - ap_id: inserted_post.ap_id.clone(), + ap_id: Url::parse(&format!("https://lemmy-alpha/post/{}", inserted_post.id)) + .unwrap() + .into(), local: true, language_id: Default::default(), featured_community: false, diff --git a/crates/db_schema/src/impls/private_message.rs b/crates/db_schema/src/impls/private_message.rs index 3cbfd052d..fe3629a1a 100644 --- a/crates/db_schema/src/impls/private_message.rs +++ b/crates/db_schema/src/impls/private_message.rs @@ -100,6 +100,7 @@ mod tests { }; use pretty_assertions::assert_eq; use serial_test::serial; + use url::Url; #[tokio::test] #[serial] @@ -138,7 +139,12 @@ mod tests { read: false, updated: None, published: inserted_private_message.published, - ap_id: inserted_private_message.ap_id.clone(), + ap_id: Url::parse(&format!( + "https://lemmy-alpha/private_message/{}", + inserted_private_message.id + )) + .unwrap() + .into(), local: true, }; diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index 6761adeee..cca449b0e 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -30,7 +30,8 @@ use diesel_async::{ AsyncDieselConnectionManager, ManagerConfig, }, - SimpleAsyncConnection, + AsyncConnection, + RunQueryDsl, }; use futures_util::{future::BoxFuture, Future, FutureExt}; use i_love_jesus::CursorKey; @@ -332,34 +333,50 @@ pub fn diesel_url_create(opt: Option<&str>) -> LemmyResult> { fn establish_connection(config: &str) -> BoxFuture> { let fut = async { - rustls::crypto::ring::default_provider() - .install_default() - .expect("Failed to install rustls crypto provider"); + // We only support TLS with sslmode=require currently + let mut conn = if config.contains("sslmode=require") { + rustls::crypto::ring::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); - let rustls_config = DangerousClientConfigBuilder { - cfg: ClientConfig::builder(), - } - .with_custom_certificate_verifier(Arc::new(NoCertVerifier {})) - .with_no_client_auth(); - - let tls = tokio_postgres_rustls::MakeRustlsConnect::new(rustls_config); - let (client, conn) = tokio_postgres::connect(config, tls) - .await - .map_err(|e| ConnectionError::BadConnection(e.to_string()))?; - tokio::spawn(async move { - if let Err(e) = conn.await { - error!("Database connection failed: {e}"); + let rustls_config = DangerousClientConfigBuilder { + cfg: ClientConfig::builder(), } - }); - let mut conn = AsyncPgConnection::try_from(client).await?; - // * Change geqo_threshold back to default value if it was changed, so it's higher than the - // collapse limits - // * Change collapse limits from 8 to 11 so the query planner can find a better table join order - // for more complicated queries - conn - .batch_execute("SET geqo_threshold=12;SET from_collapse_limit=11;SET join_collapse_limit=11;") - .await - .map_err(ConnectionError::CouldntSetupConfiguration)?; + .with_custom_certificate_verifier(Arc::new(NoCertVerifier {})) + .with_no_client_auth(); + + let tls = tokio_postgres_rustls::MakeRustlsConnect::new(rustls_config); + let (client, conn) = tokio_postgres::connect(config, tls) + .await + .map_err(|e| ConnectionError::BadConnection(e.to_string()))?; + tokio::spawn(async move { + if let Err(e) = conn.await { + error!("Database connection failed: {e}"); + } + }); + AsyncPgConnection::try_from(client).await? + } else { + AsyncPgConnection::establish(config).await? + }; + + diesel::select(( + // Change geqo_threshold back to default value if it was changed, so it's higher than the + // collapse limits + functions::set_config("geqo_threshold", "12", false), + // Change collapse limits from 8 to 11 so the query planner can find a better table join + // order for more complicated queries + functions::set_config("from_collapse_limit", "11", false), + functions::set_config("join_collapse_limit", "11", false), + // Set `lemmy.protocol_and_hostname` so triggers can use it + functions::set_config( + "lemmy.protocol_and_hostname", + SETTINGS.get_protocol_and_hostname(), + false, + ), + )) + .execute(&mut conn) + .await + .map_err(ConnectionError::CouldntSetupConfiguration)?; Ok(conn) }; fut.boxed() @@ -418,17 +435,11 @@ impl ServerCertVerifier for NoCertVerifier { pub async fn build_db_pool() -> LemmyResult { let db_url = SETTINGS.get_database_url(); - // We only support TLS with sslmode=require currently - let tls_enabled = db_url.contains("sslmode=require"); - let manager = if tls_enabled { - // diesel-async does not support any TLS connections out of the box, so we need to manually - // provide a setup function which handles creating the connection - let mut config = ManagerConfig::default(); - config.custom_setup = Box::new(establish_connection); - AsyncDieselConnectionManager::::new_with_config(&db_url, config) - } else { - AsyncDieselConnectionManager::::new(&db_url) - }; + // diesel-async does not support any TLS connections out of the box, so we need to manually + // provide a setup function which handles creating the connection + let mut config = ManagerConfig::default(); + config.custom_setup = Box::new(establish_connection); + let manager = AsyncDieselConnectionManager::::new_with_config(&db_url, config); let pool = Pool::builder(manager) .max_size(SETTINGS.database.pool_size) .runtime(Runtime::Tokio1) @@ -485,7 +496,7 @@ static EMAIL_REGEX: Lazy = Lazy::new(|| { }); pub mod functions { - use diesel::sql_types::{BigInt, Text, Timestamptz}; + use diesel::sql_types::{BigInt, Bool, Text, Timestamptz}; sql_function! { #[sql_name = "r.hot_rank"] @@ -508,6 +519,8 @@ pub mod functions { // really this function is variadic, this just adds the two-argument version sql_function!(fn coalesce(x: diesel::sql_types::Nullable, y: T) -> T); + + sql_function!(fn set_config(setting_name: Text, new_value: Text, is_local: Bool) -> Text); } pub const DELETED_REPLACEMENT_TEXT: &str = "*Permanently Deleted*"; diff --git a/migrations/2024-06-24-000000_ap_id_triggers/down.sql b/migrations/2024-06-24-000000_ap_id_triggers/down.sql new file mode 100644 index 000000000..72312eccf --- /dev/null +++ b/migrations/2024-06-24-000000_ap_id_triggers/down.sql @@ -0,0 +1,9 @@ +ALTER TABLE comment + ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme (); + +ALTER TABLE post + ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme (); + +ALTER TABLE private_message + ALTER COLUMN ap_id SET DEFAULT generate_unique_changeme (); + diff --git a/migrations/2024-06-24-000000_ap_id_triggers/up.sql b/migrations/2024-06-24-000000_ap_id_triggers/up.sql new file mode 100644 index 000000000..86e266d46 --- /dev/null +++ b/migrations/2024-06-24-000000_ap_id_triggers/up.sql @@ -0,0 +1,9 @@ +ALTER TABLE comment + ALTER COLUMN ap_id DROP DEFAULT; + +ALTER TABLE post + ALTER COLUMN ap_id DROP DEFAULT; + +ALTER TABLE private_message + ALTER COLUMN ap_id DROP DEFAULT; + From 32cee9cbca3f1ab0954e80964cfc433dbf69877e Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 7 Jul 2024 12:28:42 -0400 Subject: [PATCH 12/69] Fixing not being able to create comments on local community posts. (#4854) * Fixing not being able to create comments on local community posts. - This was caused by not passing my_person_id into various `CommentView::read` functions. - Fixes #4853 * Refactoring views to use local_user, rather than person * Addressing PR comments. * Fixing API tests. --- crates/api/src/comment/distinguish.rs | 12 +- crates/api/src/comment/like.rs | 10 +- crates/api/src/comment/list_comment_likes.rs | 2 +- crates/api/src/comment/save.rs | 11 +- crates/api/src/comment_report/create.rs | 10 +- crates/api/src/community/block.rs | 12 +- crates/api/src/community/follow.rs | 13 ++- crates/api/src/community/transfer.rs | 13 ++- crates/api/src/post/feature.rs | 8 +- crates/api/src/post/like.rs | 8 +- crates/api/src/post/lock.rs | 8 +- crates/api/src/post/save.rs | 11 +- crates/api/src/site/purge/comment.rs | 10 +- crates/api_common/src/build_response.rs | 16 +-- crates/api_crud/src/comment/create.rs | 2 +- crates/api_crud/src/comment/delete.rs | 10 +- crates/api_crud/src/comment/remove.rs | 20 ++-- crates/api_crud/src/comment/update.rs | 10 +- crates/api_crud/src/post/create.rs | 2 +- crates/api_crud/src/post/delete.rs | 2 +- crates/api_crud/src/post/read.rs | 17 ++- crates/api_crud/src/post/remove.rs | 8 +- crates/api_crud/src/post/update.rs | 2 +- crates/apub/src/api/read_community.rs | 4 +- crates/apub/src/api/resolve_object.rs | 17 +-- crates/db_schema/src/impls/local_user.rs | 23 +++- crates/db_schema/src/utils.rs | 24 +--- crates/db_views/src/comment_view.rs | 40 +++---- crates/db_views/src/post_view.rs | 110 ++++++++++--------- crates/db_views_actor/src/community_view.rs | 41 +++---- 30 files changed, 242 insertions(+), 234 deletions(-) diff --git a/crates/api/src/comment/distinguish.rs b/crates/api/src/comment/distinguish.rs index dfd850e89..0683af9a4 100644 --- a/crates/api/src/comment/distinguish.rs +++ b/crates/api/src/comment/distinguish.rs @@ -17,9 +17,13 @@ pub async fn distinguish_comment( context: Data, local_user_view: LocalUserView, ) -> LemmyResult> { - let orig_comment = CommentView::read(&mut context.pool(), data.comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let orig_comment = CommentView::read( + &mut context.pool(), + data.comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; check_community_user_action( &local_user_view.person, @@ -54,7 +58,7 @@ pub async fn distinguish_comment( let comment_view = CommentView::read( &mut context.pool(), data.comment_id, - Some(local_user_view.person.id), + Some(&local_user_view.local_user), ) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; diff --git a/crates/api/src/comment/like.rs b/crates/api/src/comment/like.rs index d0aa4a6c2..b8a1c6f76 100644 --- a/crates/api/src/comment/like.rs +++ b/crates/api/src/comment/like.rs @@ -35,9 +35,13 @@ pub async fn like_comment( check_bot_account(&local_user_view.person)?; let comment_id = data.comment_id; - let orig_comment = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let orig_comment = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; check_community_user_action( &local_user_view.person, diff --git a/crates/api/src/comment/list_comment_likes.rs b/crates/api/src/comment/list_comment_likes.rs index 8c2c9dd32..4b2e1c8b3 100644 --- a/crates/api/src/comment/list_comment_likes.rs +++ b/crates/api/src/comment/list_comment_likes.rs @@ -17,7 +17,7 @@ pub async fn list_comment_likes( let comment_view = CommentView::read( &mut context.pool(), data.comment_id, - Some(local_user_view.person.id), + Some(&local_user_view.local_user), ) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; diff --git a/crates/api/src/comment/save.rs b/crates/api/src/comment/save.rs index f9d649e48..67c2db331 100644 --- a/crates/api/src/comment/save.rs +++ b/crates/api/src/comment/save.rs @@ -32,10 +32,13 @@ pub async fn save_comment( } let comment_id = data.comment_id; - let person_id = local_user_view.person.id; - let comment_view = CommentView::read(&mut context.pool(), comment_id, Some(person_id)) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let comment_view = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; Ok(Json(CommentResponse { comment_view, diff --git a/crates/api/src/comment_report/create.rs b/crates/api/src/comment_report/create.rs index c008d1df2..a269df07f 100644 --- a/crates/api/src/comment_report/create.rs +++ b/crates/api/src/comment_report/create.rs @@ -35,9 +35,13 @@ pub async fn create_comment_report( let person_id = local_user_view.person.id; let comment_id = data.comment_id; - let comment_view = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let comment_view = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; check_community_user_action( &local_user_view.person, diff --git a/crates/api/src/community/block.rs b/crates/api/src/community/block.rs index 449addf32..ad31548ea 100644 --- a/crates/api/src/community/block.rs +++ b/crates/api/src/community/block.rs @@ -50,10 +50,14 @@ pub async fn block_community( .with_lemmy_type(LemmyErrorType::CommunityBlockAlreadyExists)?; } - let community_view = - CommunityView::read(&mut context.pool(), community_id, Some(person_id), false) - .await? - .ok_or(LemmyErrorType::CouldntFindCommunity)?; + let community_view = CommunityView::read( + &mut context.pool(), + community_id, + Some(&local_user_view.local_user), + false, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindCommunity)?; ActivityChannel::submit_activity( SendActivityData::FollowCommunity( diff --git a/crates/api/src/community/follow.rs b/crates/api/src/community/follow.rs index 853cfde14..2236fa5bc 100644 --- a/crates/api/src/community/follow.rs +++ b/crates/api/src/community/follow.rs @@ -62,11 +62,14 @@ 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), false) - .await? - .ok_or(LemmyErrorType::CouldntFindCommunity)?; + let community_view = CommunityView::read( + &mut context.pool(), + community_id, + Some(&local_user_view.local_user), + false, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindCommunity)?; let discussion_languages = CommunityLanguage::read(&mut context.pool(), community_id).await?; diff --git a/crates/api/src/community/transfer.rs b/crates/api/src/community/transfer.rs index 5f3a6032e..a32c069b1 100644 --- a/crates/api/src/community/transfer.rs +++ b/crates/api/src/community/transfer.rs @@ -76,11 +76,14 @@ pub async fn transfer_community( ModTransferCommunity::create(&mut context.pool(), &form).await?; 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), false) - .await? - .ok_or(LemmyErrorType::CouldntFindCommunity)?; + let community_view = CommunityView::read( + &mut context.pool(), + community_id, + Some(&local_user_view.local_user), + false, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindCommunity)?; let community_id = data.community_id; let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id) diff --git a/crates/api/src/post/feature.rs b/crates/api/src/post/feature.rs index 40cbf6794..ec99a3345 100644 --- a/crates/api/src/post/feature.rs +++ b/crates/api/src/post/feature.rs @@ -72,11 +72,5 @@ pub async fn feature_post( ) .await?; - build_post_response( - &context, - orig_post.community_id, - &local_user_view.person, - post_id, - ) - .await + build_post_response(&context, orig_post.community_id, local_user_view, post_id).await } diff --git a/crates/api/src/post/like.rs b/crates/api/src/post/like.rs index fccd9f8df..e6903fb3c 100644 --- a/crates/api/src/post/like.rs +++ b/crates/api/src/post/like.rs @@ -85,11 +85,5 @@ pub async fn like_post( ) .await?; - build_post_response( - context.deref(), - post.community_id, - &local_user_view.person, - post_id, - ) - .await + build_post_response(context.deref(), post.community_id, local_user_view, post_id).await } diff --git a/crates/api/src/post/lock.rs b/crates/api/src/post/lock.rs index 05db8ebbb..36f9c2a33 100644 --- a/crates/api/src/post/lock.rs +++ b/crates/api/src/post/lock.rs @@ -63,11 +63,5 @@ pub async fn lock_post( ) .await?; - build_post_response( - &context, - orig_post.community_id, - &local_user_view.person, - post_id, - ) - .await + build_post_response(&context, orig_post.community_id, local_user_view, post_id).await } diff --git a/crates/api/src/post/save.rs b/crates/api/src/post/save.rs index 96dd85579..85dfc11e3 100644 --- a/crates/api/src/post/save.rs +++ b/crates/api/src/post/save.rs @@ -34,9 +34,14 @@ pub async fn save_post( 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), false) - .await? - .ok_or(LemmyErrorType::CouldntFindPost)?; + let post_view = PostView::read( + &mut context.pool(), + post_id, + Some(&local_user_view.local_user), + false, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindPost)?; mark_post_as_read(person_id, post_id, &mut context.pool()).await?; diff --git a/crates/api/src/site/purge/comment.rs b/crates/api/src/site/purge/comment.rs index 70d95e160..f99dfc689 100644 --- a/crates/api/src/site/purge/comment.rs +++ b/crates/api/src/site/purge/comment.rs @@ -29,9 +29,13 @@ pub async fn purge_comment( let comment_id = data.comment_id; // Read the comment to get the post_id and community - let comment_view = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let comment_view = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; let post_id = comment_view.comment.post_id; diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index 85cf065eb..200284b00 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -36,8 +36,8 @@ pub async fn build_comment_response( local_user_view: Option, recipient_ids: Vec, ) -> LemmyResult { - let person_id = local_user_view.map(|l| l.person.id); - let comment_view = CommentView::read(&mut context.pool(), comment_id, person_id) + let local_user = local_user_view.map(|l| l.local_user); + let comment_view = CommentView::read(&mut context.pool(), comment_id, local_user.as_ref()) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; Ok(CommentResponse { @@ -54,11 +54,11 @@ pub async fn build_community_response( let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id) .await .is_ok(); - let person_id = local_user_view.person.id; + let local_user = local_user_view.local_user; let community_view = CommunityView::read( &mut context.pool(), community_id, - Some(person_id), + Some(&local_user), is_mod_or_admin, ) .await? @@ -74,16 +74,17 @@ pub async fn build_community_response( pub async fn build_post_response( context: &LemmyContext, community_id: CommunityId, - person: &Person, + local_user_view: LocalUserView, post_id: PostId, ) -> LemmyResult> { - let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), person, community_id) + let local_user = local_user_view.local_user; + let is_mod_or_admin = is_mod_or_admin(&mut context.pool(), &local_user_view.person, community_id) .await .is_ok(); let post_view = PostView::read( &mut context.pool(), post_id, - Some(person.id), + Some(&local_user), is_mod_or_admin, ) .await? @@ -103,6 +104,7 @@ pub async fn send_local_notifs( let mut recipient_ids = Vec::new(); let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname()); + // let person = my_local_user.person; // Read the comment view to get extra info let comment_view = CommentView::read(&mut context.pool(), comment_id, None) .await? diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index ff3efd946..b7c65740c 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -54,7 +54,7 @@ pub async fn create_comment( let post_view = PostView::read( &mut context.pool(), post_id, - Some(local_user_view.person.id), + Some(&local_user_view.local_user), true, ) .await? diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index 2b1a20f89..29706d365 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -21,9 +21,13 @@ pub async fn delete_comment( local_user_view: LocalUserView, ) -> LemmyResult> { let comment_id = data.comment_id; - let orig_comment = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let orig_comment = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; // Dont delete it if its already been deleted. if orig_comment.comment.deleted == data.deleted { diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index 926472b94..83ef82e3a 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -25,9 +25,13 @@ pub async fn remove_comment( local_user_view: LocalUserView, ) -> LemmyResult> { let comment_id = data.comment_id; - let orig_comment = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let orig_comment = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; check_community_mod_action( &local_user_view.person, @@ -68,14 +72,8 @@ pub async fn remove_comment( }; ModRemoveComment::create(&mut context.pool(), &form).await?; - let recipient_ids = send_local_notifs( - vec![], - comment_id, - &local_user_view.person.clone(), - false, - &context, - ) - .await?; + let recipient_ids = + send_local_notifs(vec![], comment_id, &local_user_view.person, false, &context).await?; let updated_comment_id = updated_comment.id; ActivityChannel::submit_activity( diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 4c8cf9436..32bd08240 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -36,9 +36,13 @@ pub async fn update_comment( let local_site = LocalSite::read(&mut context.pool()).await?; let comment_id = data.comment_id; - let orig_comment = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let orig_comment = CommentView::read( + &mut context.pool(), + comment_id, + Some(&local_user_view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; check_community_user_action( &local_user_view.person, diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 39ef8ce09..0f6abc2aa 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -188,5 +188,5 @@ pub async fn create_post( } }; - build_post_response(&context, community_id, &local_user_view.person, post_id).await + build_post_response(&context, community_id, local_user_view, post_id).await } diff --git a/crates/api_crud/src/post/delete.rs b/crates/api_crud/src/post/delete.rs index 696566c8e..6834030ac 100644 --- a/crates/api_crud/src/post/delete.rs +++ b/crates/api_crud/src/post/delete.rs @@ -62,7 +62,7 @@ pub async fn delete_post( build_post_response( &context, orig_post.community_id, - &local_user_view.person, + local_user_view, data.post_id, ) .await diff --git a/crates/api_crud/src/post/read.rs b/crates/api_crud/src/post/read.rs index 60b5609a9..ebf8940a2 100644 --- a/crates/api_crud/src/post/read.rs +++ b/crates/api_crud/src/post/read.rs @@ -55,9 +55,15 @@ pub async fn get_post( .await .is_ok(); - let post_view = PostView::read(&mut context.pool(), post_id, person_id, is_mod_or_admin) - .await? - .ok_or(LemmyErrorType::CouldntFindPost)?; + let local_user = local_user_view.map(|l| l.local_user); + let post_view = PostView::read( + &mut context.pool(), + post_id, + local_user.as_ref(), + is_mod_or_admin, + ) + .await? + .ok_or(LemmyErrorType::CouldntFindPost)?; let post_id = post_view.post.id; if let Some(person_id) = person_id { @@ -76,20 +82,19 @@ pub async fn get_post( let community_view = CommunityView::read( &mut context.pool(), community_id, - person_id, + local_user.as_ref(), is_mod_or_admin, ) .await? .ok_or(LemmyErrorType::CouldntFindCommunity)?; let moderators = CommunityModeratorView::for_community(&mut context.pool(), community_id).await?; - let local_user = local_user_view.as_ref().map(|u| &u.local_user); // Fetch the cross_posts let cross_posts = if let Some(url) = &post_view.post.url { let mut x_posts = PostQuery { url_search: Some(url.inner().as_str().into()), - local_user, + local_user: local_user.as_ref(), ..Default::default() } .list(&local_site.site, &mut context.pool()) diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs index 682ed75d3..4ca15c90f 100644 --- a/crates/api_crud/src/post/remove.rs +++ b/crates/api_crud/src/post/remove.rs @@ -73,11 +73,5 @@ pub async fn remove_post( ) .await?; - build_post_response( - &context, - orig_post.community_id, - &local_user_view.person, - post_id, - ) - .await + build_post_response(&context, orig_post.community_id, local_user_view, post_id).await } diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index 9e665aed6..cd4b2d41b 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -137,7 +137,7 @@ pub async fn update_post( build_post_response( context.deref(), orig_post.community_id, - &local_user_view.person, + local_user_view, post_id, ) .await diff --git a/crates/apub/src/api/read_community.rs b/crates/apub/src/api/read_community.rs index dae7719ae..62fd6ec0b 100644 --- a/crates/apub/src/api/read_community.rs +++ b/crates/apub/src/api/read_community.rs @@ -29,7 +29,7 @@ pub async fn get_community( check_private_instance(&local_user_view, &local_site)?; - let person_id = local_user_view.as_ref().map(|u| u.person.id); + let local_user = local_user_view.as_ref().map(|u| &u.local_user); let community_id = match data.id { Some(id) => id, @@ -53,7 +53,7 @@ pub async fn get_community( let community_view = CommunityView::read( &mut context.pool(), community_id, - person_id, + local_user, is_mod_or_admin, ) .await? diff --git a/crates/apub/src/api/resolve_object.rs b/crates/apub/src/api/resolve_object.rs index 47f6c5d06..3f2591241 100644 --- a/crates/apub/src/api/resolve_object.rs +++ b/crates/apub/src/api/resolve_object.rs @@ -10,7 +10,7 @@ use lemmy_api_common::{ site::{ResolveObject, ResolveObjectResponse}, utils::check_private_instance, }; -use lemmy_db_schema::{newtypes::PersonId, source::local_site::LocalSite, utils::DbPool}; +use lemmy_db_schema::{source::local_site::LocalSite, utils::DbPool}; use lemmy_db_views::structs::{CommentView, LocalUserView, PostView}; use lemmy_db_views_actor::structs::{CommunityView, PersonView}; use lemmy_utils::error::{LemmyErrorExt2, LemmyErrorType, LemmyResult}; @@ -23,10 +23,9 @@ pub async fn resolve_object( ) -> LemmyResult> { let local_site = LocalSite::read(&mut context.pool()).await?; check_private_instance(&local_user_view, &local_site)?; - let person_id = local_user_view.map(|v| v.person.id); // If we get a valid personId back we can safely assume that the user is authenticated, // if there's no personId then the JWT was missing or invalid. - let is_authenticated = person_id.is_some(); + let is_authenticated = local_user_view.is_some(); let res = if is_authenticated { // user is fully authenticated; allow remote lookups as well. @@ -37,24 +36,26 @@ pub async fn resolve_object( } .with_lemmy_type(LemmyErrorType::CouldntFindObject)?; - convert_response(res, person_id, &mut context.pool()) + convert_response(res, local_user_view, &mut context.pool()) .await .with_lemmy_type(LemmyErrorType::CouldntFindObject) } async fn convert_response( object: SearchableObjects, - user_id: Option, + local_user_view: Option, pool: &mut DbPool<'_>, ) -> LemmyResult> { use SearchableObjects::*; let removed_or_deleted; let mut res = ResolveObjectResponse::default(); + let local_user = local_user_view.map(|l| l.local_user); + match object { Post(p) => { removed_or_deleted = p.deleted || p.removed; res.post = Some( - PostView::read(pool, p.id, user_id, false) + PostView::read(pool, p.id, local_user.as_ref(), false) .await? .ok_or(LemmyErrorType::CouldntFindPost)?, ) @@ -62,7 +63,7 @@ async fn convert_response( Comment(c) => { removed_or_deleted = c.deleted || c.removed; res.comment = Some( - CommentView::read(pool, c.id, user_id) + CommentView::read(pool, c.id, local_user.as_ref()) .await? .ok_or(LemmyErrorType::CouldntFindComment)?, ) @@ -79,7 +80,7 @@ async fn convert_response( UserOrCommunity::Community(c) => { removed_or_deleted = c.deleted || c.removed; res.community = Some( - CommunityView::read(pool, c.id, user_id, false) + CommunityView::read(pool, c.id, local_user.as_ref(), false) .await? .ok_or(LemmyErrorType::CouldntFindCommunity)?, ) diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 9b59e07ba..694979ade 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -1,6 +1,6 @@ use crate::{ newtypes::{DbUrl, LanguageId, LocalUserId, PersonId}, - schema::{local_user, person, registration_application}, + schema::{community, local_user, person, registration_application}, source::{ actor_language::LocalUserLanguage, local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm}, @@ -13,6 +13,7 @@ use crate::{ now, DbPool, }, + CommunityVisibility, }; use bcrypt::{hash, DEFAULT_COST}; use diesel::{ @@ -225,6 +226,12 @@ pub trait LocalUserOptionHelper { fn show_read_posts(&self) -> bool; fn is_admin(&self) -> bool; fn show_nsfw(&self, site: &Site) -> bool; + fn visible_communities_only(&self, query: Q) -> Q + where + Q: diesel::query_dsl::methods::FilterDsl< + diesel::dsl::Eq, + Output = Q, + >; } impl LocalUserOptionHelper for Option<&LocalUser> { @@ -253,6 +260,20 @@ impl LocalUserOptionHelper for Option<&LocalUser> { .map(|l| l.show_nsfw) .unwrap_or(site.content_warning.is_some()) } + + fn visible_communities_only(&self, query: Q) -> Q + where + Q: diesel::query_dsl::methods::FilterDsl< + diesel::dsl::Eq, + Output = Q, + >, + { + if self.is_none() { + query.filter(community::visibility.eq(CommunityVisibility::Public)) + } else { + query + } + } } impl LocalUserInsertForm { diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index cca449b0e..ec9f9ded7 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -1,15 +1,7 @@ -use crate::{ - diesel::ExpressionMethods, - newtypes::{DbUrl, PersonId}, - schema::community, - CommentSortType, - CommunityVisibility, - SortType, -}; +use crate::{newtypes::DbUrl, CommentSortType, SortType}; use chrono::{DateTime, TimeDelta, Utc}; use deadpool::Runtime; use diesel::{ - dsl, helper_types::AsExprOf, pg::Pg, query_builder::{Query, QueryFragment}, @@ -592,20 +584,6 @@ impl Queries { } } -pub fn visible_communities_only(my_person_id: Option, query: Q) -> Q -where - Q: diesel::query_dsl::methods::FilterDsl< - dsl::Eq, - Output = Q, - >, -{ - if my_person_id.is_none() { - query.filter(community::visibility.eq(CommunityVisibility::Public)) - } else { - query - } -} - #[cfg(test)] #[allow(clippy::indexing_slicing)] mod tests { diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index cd7560a00..0e476b3b6 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -36,22 +36,13 @@ use lemmy_db_schema::{ post, }, source::local_user::LocalUser, - utils::{ - fuzzy_search, - limit_and_offset, - visible_communities_only, - DbConn, - DbPool, - ListFn, - Queries, - ReadFn, - }, + utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, CommentSortType, ListingType, }; fn queries<'a>() -> Queries< - impl ReadFn<'a, CommentView, (CommentId, Option)>, + impl ReadFn<'a, CommentView, (CommentId, Option<&'a LocalUser>)>, impl ListFn<'a, CommentView, CommentQuery<'a>>, > { let is_creator_banned_from_community = exists( @@ -182,9 +173,12 @@ fn queries<'a>() -> Queries< }; let read = move |mut conn: DbConn<'a>, - (comment_id, my_person_id): (CommentId, Option)| async move { - let mut query = all_joins(comment::table.find(comment_id).into_boxed(), my_person_id); - query = visible_communities_only(my_person_id, query); + (comment_id, my_local_user): (CommentId, Option<&'a LocalUser>)| async move { + let mut query = all_joins( + comment::table.find(comment_id).into_boxed(), + my_local_user.person_id(), + ); + query = my_local_user.visible_communities_only(query); query.first(&mut conn).await }; @@ -301,7 +295,7 @@ fn queries<'a>() -> Queries< query = query.filter(not(is_creator_blocked(person_id_join))); }; - query = visible_communities_only(options.local_user.person_id(), query); + query = options.local_user.visible_communities_only(query); // A Max depth given means its a tree fetch let (limit, offset) = if let Some(max_depth) = options.max_depth { @@ -366,16 +360,16 @@ fn queries<'a>() -> Queries< } impl CommentView { - pub async fn read( + pub async fn read<'a>( pool: &mut DbPool<'_>, comment_id: CommentId, - my_person_id: Option, + my_local_user: Option<&'a LocalUser>, ) -> Result, Error> { // If a person is given, then my_vote (res.9), if None, should be 0, not null // Necessary to differentiate between other person's votes - if let Ok(Some(res)) = queries().read(pool, (comment_id, my_person_id)).await { + if let Ok(Some(res)) = queries().read(pool, (comment_id, my_local_user)).await { let mut new_view = res.clone(); - if my_person_id.is_some() && res.my_vote.is_none() { + if my_local_user.is_some() && res.my_vote.is_none() { new_view.my_vote = Some(0); } if res.comment.deleted || res.comment.removed { @@ -676,7 +670,7 @@ mod tests { let read_comment_from_blocked_person = CommentView::read( pool, data.inserted_comment_1.id, - Some(data.timmy_local_user_view.person.id), + Some(&data.timmy_local_user_view.local_user), ) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; @@ -1171,7 +1165,7 @@ mod tests { let authenticated_comment = CommentView::read( pool, data.inserted_comment_0.id, - Some(data.timmy_local_user_view.person.id), + Some(&data.timmy_local_user_view.local_user), ) .await; assert!(authenticated_comment.is_ok()); @@ -1211,7 +1205,7 @@ mod tests { let comment_view = CommentView::read( pool, data.inserted_comment_0.id, - Some(inserted_banned_from_comm_local_user.person_id), + Some(&inserted_banned_from_comm_local_user), ) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; @@ -1232,7 +1226,7 @@ mod tests { let comment_view = CommentView::read( pool, data.inserted_comment_0.id, - Some(data.timmy_local_user_view.person.id), + Some(&data.timmy_local_user_view.local_user), ) .await? .ok_or(LemmyErrorType::CouldntFindComment)?; diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 0e22f689b..588bb017b 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -49,7 +49,6 @@ use lemmy_db_schema::{ get_conn, limit_and_offset, now, - visible_communities_only, Commented, DbConn, DbPool, @@ -64,7 +63,7 @@ use lemmy_db_schema::{ use tracing::debug; fn queries<'a>() -> Queries< - impl ReadFn<'a, PostView, (PostId, Option, bool)>, + impl ReadFn<'a, PostView, (PostId, Option<&'a LocalUser>, bool)>, impl ListFn<'a, PostView, (PostQuery<'a>, &'a Site)>, > { let is_creator_banned_from_community = exists( @@ -142,6 +141,7 @@ fn queries<'a>() -> Queries< .single_value() }; + // TODO maybe this should go to localuser also let all_joins = move |query: post_aggregates::BoxedQuery<'a, Pg>, my_person_id: Option| { let is_local_user_banned_from_community_selection: Box< @@ -250,52 +250,56 @@ fn queries<'a>() -> Queries< )) }; - 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 read = move |mut conn: DbConn<'a>, + (post_id, my_local_user, is_mod_or_admin): ( + PostId, + Option<&'a LocalUser>, + bool, + )| async move { + // The left join below will return None in this case + let my_person_id = my_local_user.person_id(); + 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, - ); + let mut query = all_joins( + post_aggregates::table + .filter(post_aggregates::post_id.eq(post_id)) + .into_boxed(), + my_person_id, + ); - // Hide deleted and removed for non-admins or mods - if !is_mod_or_admin { - query = query - .filter( - community::removed - .eq(false) - .or(post::creator_id.eq(person_id_join)), - ) - .filter( - post::removed - .eq(false) - .or(post::creator_id.eq(person_id_join)), - ) - // 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) + .or(post::creator_id.eq(person_id_join)), + ) + .filter( + post::removed + .eq(false) + .or(post::creator_id.eq(person_id_join)), + ) + // 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 = visible_communities_only(my_person_id, query); + query = my_local_user.visible_communities_only(query); - Commented::new(query) - .text("PostView::read") - .first(&mut conn) - .await - }; + Commented::new(query) + .text("PostView::read") + .first(&mut conn) + .await + }; let list = move |mut conn: DbConn<'a>, (options, site): (PostQuery<'a>, &'a Site)| async move { // The left join below will return None in this case @@ -437,7 +441,7 @@ fn queries<'a>() -> Queries< } }; - query = visible_communities_only(options.local_user.person_id(), query); + query = options.local_user.visible_communities_only(query); // Dont filter blocks or missing languages for moderator view type if let (Some(person_id), false) = ( @@ -552,14 +556,14 @@ fn queries<'a>() -> Queries< } impl PostView { - pub async fn read( + pub async fn read<'a>( pool: &mut DbPool<'_>, post_id: PostId, - my_person_id: Option, + my_local_user: Option<&'a LocalUser>, is_mod_or_admin: bool, ) -> Result, Error> { queries() - .read(pool, (post_id, my_person_id, is_mod_or_admin)) + .read(pool, (post_id, my_local_user, is_mod_or_admin)) .await } } @@ -938,7 +942,7 @@ mod tests { let post_listing_single_with_person = PostView::read( pool, data.inserted_post.id, - Some(data.local_user_view.person.id), + Some(&data.local_user_view.local_user), false, ) .await? @@ -1067,7 +1071,7 @@ mod tests { let post_listing_single_with_person = PostView::read( pool, data.inserted_post.id, - Some(data.local_user_view.person.id), + Some(&data.local_user_view.local_user), false, ) .await? @@ -1755,7 +1759,7 @@ mod tests { let authenticated_post = PostView::read( pool, data.inserted_post.id, - Some(data.local_user_view.person.id), + Some(&data.local_user_view.local_user), false, ) .await; @@ -1797,7 +1801,7 @@ mod tests { let post_view = PostView::read( pool, data.inserted_post.id, - Some(inserted_banned_from_comm_local_user.person_id), + Some(&inserted_banned_from_comm_local_user), false, ) .await? @@ -1819,7 +1823,7 @@ mod tests { let post_view = PostView::read( pool, data.inserted_post.id, - Some(data.local_user_view.person.id), + Some(&data.local_user_view.local_user), false, ) .await? diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index 25e76c7b3..7d8a7277f 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -22,27 +22,18 @@ use lemmy_db_schema::{ instance_block, }, source::{community::CommunityFollower, local_user::LocalUser, site::Site}, - utils::{ - fuzzy_search, - limit_and_offset, - visible_communities_only, - DbConn, - DbPool, - ListFn, - Queries, - ReadFn, - }, + utils::{fuzzy_search, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, ListingType, SortType, }; fn queries<'a>() -> Queries< - impl ReadFn<'a, CommunityView, (CommunityId, Option, bool)>, + impl ReadFn<'a, CommunityView, (CommunityId, Option<&'a LocalUser>, bool)>, impl ListFn<'a, CommunityView, (CommunityQuery<'a>, &'a Site)>, > { - let all_joins = |query: community::BoxedQuery<'a, Pg>, my_person_id: Option| { + let all_joins = |query: community::BoxedQuery<'a, Pg>, my_local_user: Option<&'a LocalUser>| { // The left join below will return None in this case - let person_id_join = my_person_id.unwrap_or(PersonId(-1)); + let person_id_join = my_local_user.person_id().unwrap_or(PersonId(-1)); query .inner_join(community_aggregates::table) @@ -89,14 +80,14 @@ fn queries<'a>() -> Queries< .and(community::deleted.eq(false)); let read = move |mut conn: DbConn<'a>, - (community_id, my_person_id, is_mod_or_admin): ( + (community_id, my_local_user, is_mod_or_admin): ( CommunityId, - Option, + Option<&'a LocalUser>, bool, )| async move { let mut query = all_joins( community::table.find(community_id).into_boxed(), - my_person_id, + my_local_user, ) .select(selection); @@ -105,7 +96,7 @@ fn queries<'a>() -> Queries< query = query.filter(not_removed_or_deleted); } - query = visible_communities_only(my_person_id, query); + query = my_local_user.visible_communities_only(query); query.first(&mut conn).await }; @@ -116,11 +107,7 @@ fn queries<'a>() -> Queries< // The left join below will return None in this case let person_id_join = options.local_user.person_id().unwrap_or(PersonId(-1)); - let mut query = all_joins( - community::table.into_boxed(), - options.local_user.person_id(), - ) - .select(selection); + let mut query = all_joins(community::table.into_boxed(), options.local_user).select(selection); if let Some(search_term) = options.search_term { let searcher = fuzzy_search(&search_term); @@ -173,7 +160,7 @@ fn queries<'a>() -> Queries< query = query.filter(community::nsfw.eq(false)); } - query = visible_communities_only(options.local_user.person_id(), query); + query = options.local_user.visible_communities_only(query); let (limit, offset) = limit_and_offset(options.page, options.limit)?; query @@ -187,14 +174,14 @@ fn queries<'a>() -> Queries< } impl CommunityView { - pub async fn read( + pub async fn read<'a>( pool: &mut DbPool<'_>, community_id: CommunityId, - my_person_id: Option, + my_local_user: Option<&'a LocalUser>, is_mod_or_admin: bool, ) -> Result, Error> { queries() - .read(pool, (community_id, my_person_id, is_mod_or_admin)) + .read(pool, (community_id, my_local_user, is_mod_or_admin)) .await } @@ -388,7 +375,7 @@ mod tests { let authenticated_community = CommunityView::read( pool, data.inserted_community.id, - Some(data.local_user.person_id), + Some(&data.local_user), false, ) .await; From f229f09f92f44bb67fce3801be5345d89a0b808a Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 7 Jul 2024 19:01:03 -0400 Subject: [PATCH 13/69] Changing nodeinfo test from voyager.lemmy.ml to lemmy.ml (#4891) - Fixes #4870 --- src/scheduled_tasks.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/scheduled_tasks.rs b/src/scheduled_tasks.rs index 2885b5f74..ae6187a53 100644 --- a/src/scheduled_tasks.rs +++ b/src/scheduled_tasks.rs @@ -559,9 +559,9 @@ mod tests { #[tokio::test] #[serial] - async fn test_nodeinfo_voyager_lemmy_ml() -> LemmyResult<()> { + async fn test_nodeinfo_lemmy_ml() -> LemmyResult<()> { let client = ClientBuilder::new(client_builder(&Settings::default()).build()?).build(); - let form = build_update_instance_form("voyager.lemmy.ml", &client) + let form = build_update_instance_form("lemmy.ml", &client) .await .ok_or(LemmyErrorType::CouldntFindObject)?; assert_eq!( From 53a226b9443816452c33ee10a0e4d3457f1be6a3 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 9 Jul 2024 13:44:23 -0400 Subject: [PATCH 14/69] Add show_nsfw override filter to GetPosts. (#4889) - Fixes #4124 --- crates/api_common/src/post.rs | 2 ++ crates/apub/src/api/list_posts.rs | 2 ++ crates/db_views/src/post_view.rs | 48 ++++++++++++++++++++++++++++++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/crates/api_common/src/post.rs b/crates/api_common/src/post.rs index f42a468b5..74369173b 100644 --- a/crates/api_common/src/post.rs +++ b/crates/api_common/src/post.rs @@ -81,6 +81,8 @@ pub struct GetPosts { pub show_hidden: Option, /// If true, then show the read posts (even if your user setting is to hide them) pub show_read: Option, + /// If true, then show the nsfw posts (even if your user setting is to hide them) + pub show_nsfw: Option, pub page_cursor: Option, } diff --git a/crates/apub/src/api/list_posts.rs b/crates/apub/src/api/list_posts.rs index c00c87f4c..7ceafed8d 100644 --- a/crates/apub/src/api/list_posts.rs +++ b/crates/apub/src/api/list_posts.rs @@ -43,6 +43,7 @@ pub async fn list_posts( let saved_only = data.saved_only; let show_hidden = data.show_hidden; let show_read = data.show_read; + let show_nsfw = data.show_nsfw; let liked_only = data.liked_only; let disliked_only = data.disliked_only; @@ -84,6 +85,7 @@ pub async fn list_posts( limit, show_hidden, show_read, + show_nsfw, ..Default::default() } .list(&local_site.site, &mut context.pool()) diff --git a/crates/db_views/src/post_view.rs b/crates/db_views/src/post_view.rs index 588bb017b..0ec7e0a5d 100644 --- a/crates/db_views/src/post_view.rs +++ b/crates/db_views/src/post_view.rs @@ -396,7 +396,10 @@ fn queries<'a>() -> Queries< .filter(not(post::removed.or(post::deleted))); } - if !options.local_user.show_nsfw(site) { + if !options + .show_nsfw + .unwrap_or(options.local_user.show_nsfw(site)) + { query = query .filter(post::nsfw.eq(false)) .filter(community::nsfw.eq(false)); @@ -621,6 +624,7 @@ pub struct PostQuery<'a> { pub page_back: Option, pub show_hidden: Option, pub show_read: Option, + pub show_nsfw: Option, } impl<'a> PostQuery<'a> { @@ -1589,6 +1593,48 @@ mod tests { cleanup(data, pool).await } + #[tokio::test] + #[serial] + async fn post_listings_hide_nsfw() -> LemmyResult<()> { + let pool = &build_db_pool().await?; + let pool = &mut pool.into(); + let data = init_data(pool).await?; + + // Mark a post as nsfw + let update_form = PostUpdateForm { + nsfw: Some(true), + ..Default::default() + }; + + Post::update(pool, data.inserted_bot_post.id, &update_form).await?; + + // Make sure you don't see the nsfw post in the regular results + let post_listings_hide_nsfw = data.default_post_query().list(&data.site, pool).await?; + assert_eq!(vec![POST], names(&post_listings_hide_nsfw)); + + // Make sure it does come back with the show_nsfw option + let post_listings_show_nsfw = PostQuery { + sort: Some(SortType::New), + show_nsfw: Some(true), + local_user: Some(&data.local_user_view.local_user), + ..Default::default() + } + .list(&data.site, pool) + .await?; + assert_eq!(vec![POST_BY_BOT, POST], names(&post_listings_show_nsfw)); + + // Make sure that nsfw field is true. + assert!( + &post_listings_show_nsfw + .first() + .ok_or(LemmyErrorType::CouldntFindPost)? + .post + .nsfw + ); + + cleanup(data, pool).await + } + async fn cleanup(data: Data, pool: &mut DbPool<'_>) -> LemmyResult<()> { let num_deleted = Post::delete(pool, data.inserted_post.id).await?; Community::delete(pool, data.inserted_community.id).await?; From 6ff128341cd8424b0474cf3e4a0841c3a960cae0 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 11 Jul 2024 11:31:31 -0400 Subject: [PATCH 15/69] Do pictrs transformations for proxied image urls. (#4895) - Fixes #4893 --- crates/routes/src/images.rs | 83 +++++++++++++++++++++++++++---------- 1 file changed, 60 insertions(+), 23 deletions(-) diff --git a/crates/routes/src/images.rs b/crates/routes/src/images.rs index 049bd6cc8..10ffb57de 100644 --- a/crates/routes/src/images.rs +++ b/crates/routes/src/images.rs @@ -41,12 +41,66 @@ pub fn config( .service(web::resource("/pictrs/image/delete/{token}/{filename}").route(web::get().to(delete))); } -#[derive(Deserialize)] +trait ProcessUrl { + /// If thumbnail or format is given, this uses the pictrs process endpoint. + /// Otherwise, it uses the normal pictrs url (IE image/original). + fn process_url(&self, image_url: &str, pictrs_url: &Url) -> String; +} + +#[derive(Deserialize, Clone)] struct PictrsGetParams { format: Option, thumbnail: Option, } +impl ProcessUrl for PictrsGetParams { + fn process_url(&self, src: &str, pictrs_url: &Url) -> String { + if self.format.is_none() && self.thumbnail.is_none() { + format!("{}image/original/{}", pictrs_url, src) + } else { + // Take file type from name, or jpg if nothing is given + let format = self + .clone() + .format + .unwrap_or_else(|| src.split('.').last().unwrap_or("jpg").to_string()); + + let mut url = format!("{}image/process.{}?src={}", pictrs_url, format, src); + + if let Some(size) = self.thumbnail { + url = format!("{url}&thumbnail={size}",); + } + url + } + } +} + +#[derive(Deserialize, Clone)] +pub struct ImageProxyParams { + url: String, + format: Option, + thumbnail: Option, +} + +impl ProcessUrl for ImageProxyParams { + fn process_url(&self, proxy_url: &str, pictrs_url: &Url) -> String { + if self.format.is_none() && self.thumbnail.is_none() { + format!("{}image/original?proxy={}", pictrs_url, proxy_url) + } else { + // Take file type from name, or jpg if nothing is given + let format = self + .clone() + .format + .unwrap_or_else(|| proxy_url.split('.').last().unwrap_or("jpg").to_string()); + + let mut url = format!("{}image/process.{}?proxy={}", pictrs_url, format, proxy_url); + + if let Some(size) = self.thumbnail { + url = format!("{url}&thumbnail={size}",); + } + url + } + } +} fn adapt_request( request: &HttpRequest, client: &ClientWithMiddleware, @@ -133,23 +187,10 @@ async fn full_res( // If there are no query params, the URL is original let pictrs_config = context.settings().pictrs_config()?; - let url = if params.format.is_none() && params.thumbnail.is_none() { - format!("{}image/original/{}", pictrs_config.url, name,) - } else { - // Take file type from name, or jpg if nothing is given - let format = params - .format - .unwrap_or_else(|| name.split('.').last().unwrap_or("jpg").to_string()); - let mut url = format!("{}image/process.{}?src={}", pictrs_config.url, format, name,); + let processed_url = params.process_url(name, &pictrs_config.url); - if let Some(size) = params.thumbnail { - url = format!("{url}&thumbnail={size}",); - } - url - }; - - image(url, req, &client).await + image(processed_url, req, &client).await } async fn image( @@ -208,11 +249,6 @@ async fn delete( Ok(HttpResponse::build(res.status()).body(BodyStream::new(res.bytes_stream()))) } -#[derive(Deserialize)] -pub struct ImageProxyParams { - url: String, -} - pub async fn image_proxy( Query(params): Query, req: HttpRequest, @@ -226,9 +262,10 @@ pub async fn image_proxy( RemoteImage::validate(&mut context.pool(), url.clone().into()).await?; let pictrs_config = context.settings().pictrs_config()?; - let url = format!("{}image/original?proxy={}", pictrs_config.url, ¶ms.url); - image(url, req, &client).await + let processed_url = params.process_url(¶ms.url, &pictrs_config.url); + + image(processed_url, req, &client).await } fn make_send(mut stream: S) -> impl Stream + Send + Unpin + 'static From ba044c7d987acfbdedafac16cc409ba0db7709ef Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 16 Jul 2024 06:22:47 -0400 Subject: [PATCH 16/69] Adding checks for higher admin and mod. (#4860) * Adding checks for higher admin and mod. * Adding admin/mod checks for ban and comment removal. * Combining mod or admin check with an SQL union. * Making community ban or add mod also allow higher admins. * Making sure remove post also checks higher mods or admins. * Add unit test for is_higher_mod_or_admin_check * Fixing comment. * Addressing PR comments. * Get rid of pointless wrapper functions, return lemmyresult directly. --- crates/api/src/community/add_mod.rs | 13 + crates/api/src/community/ban.rs | 9 + crates/api/src/local_user/add_admin.rs | 10 + crates/api/src/local_user/ban_person.rs | 9 + crates/api/src/site/purge/comment.rs | 9 + crates/api/src/site/purge/community.rs | 18 ++ crates/api/src/site/purge/person.rs | 10 + crates/api/src/site/purge/post.rs | 9 + crates/api_common/src/claims.rs | 5 +- crates/api_crud/src/comment/remove.rs | 9 + crates/api_crud/src/post/remove.rs | 9 + crates/api_crud/src/user/create.rs | 22 +- crates/apub/src/api/user_settings_backup.rs | 5 +- crates/db_schema/src/impls/actor_language.rs | 10 +- crates/db_schema/src/impls/community.rs | 246 +++++++++++------- crates/db_schema/src/impls/local_user.rs | 139 +++++++++- .../src/impls/password_reset_request.rs | 5 +- crates/db_schema/src/impls/person.rs | 53 ++-- crates/db_schema/src/source/local_user.rs | 30 ++- crates/db_views/src/comment_report_view.rs | 5 +- crates/db_views/src/comment_view.rs | 7 +- crates/db_views/src/post_report_view.rs | 5 +- .../src/registration_application_view.rs | 16 +- crates/db_views_actor/src/community_view.rs | 5 +- crates/db_views_actor/src/person_view.rs | 10 +- crates/utils/src/error.rs | 2 + src/code_migrations.rs | 11 +- src/session_middleware.rs | 5 +- 28 files changed, 475 insertions(+), 211 deletions(-) diff --git a/crates/api/src/community/add_mod.rs b/crates/api/src/community/add_mod.rs index 5245f592e..8d8826cd2 100644 --- a/crates/api/src/community/add_mod.rs +++ b/crates/api/src/community/add_mod.rs @@ -9,6 +9,7 @@ use lemmy_api_common::{ use lemmy_db_schema::{ source::{ community::{Community, CommunityModerator, CommunityModeratorForm}, + local_user::LocalUser, moderator::{ModAddCommunity, ModAddCommunityForm}, }, traits::{Crud, Joinable}, @@ -33,6 +34,18 @@ pub async fn add_mod_to_community( &mut context.pool(), ) .await?; + + // If its a mod removal, also check that you're a higher mod. + if !data.added { + LocalUser::is_higher_mod_or_admin_check( + &mut context.pool(), + community_id, + local_user_view.person.id, + vec![data.person_id], + ) + .await?; + } + let community = Community::read(&mut context.pool(), community_id) .await? .ok_or(LemmyErrorType::CouldntFindCommunity)?; diff --git a/crates/api/src/community/ban.rs b/crates/api/src/community/ban.rs index 877d9464f..8e527d2ac 100644 --- a/crates/api/src/community/ban.rs +++ b/crates/api/src/community/ban.rs @@ -14,6 +14,7 @@ use lemmy_db_schema::{ CommunityPersonBan, CommunityPersonBanForm, }, + local_user::LocalUser, moderator::{ModBanFromCommunity, ModBanFromCommunityForm}, }, traits::{Bannable, Crud, Followable}, @@ -44,6 +45,14 @@ pub async fn ban_from_community( ) .await?; + LocalUser::is_higher_mod_or_admin_check( + &mut context.pool(), + data.community_id, + local_user_view.person.id, + vec![data.person_id], + ) + .await?; + if let Some(reason) = &data.reason { is_valid_body_field(reason, false)?; } diff --git a/crates/api/src/local_user/add_admin.rs b/crates/api/src/local_user/add_admin.rs index 7db2e5653..44b36fe66 100644 --- a/crates/api/src/local_user/add_admin.rs +++ b/crates/api/src/local_user/add_admin.rs @@ -24,6 +24,16 @@ pub async fn add_admin( // Make sure user is an admin is_admin(&local_user_view)?; + // If its an admin removal, also check that you're a higher admin + if !data.added { + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + vec![data.person_id], + ) + .await?; + } + // Make sure that the person_id added is local let added_local_user = LocalUserView::read_person(&mut context.pool(), data.person_id) .await? diff --git a/crates/api/src/local_user/ban_person.rs b/crates/api/src/local_user/ban_person.rs index 49cd6893a..58392cefd 100644 --- a/crates/api/src/local_user/ban_person.rs +++ b/crates/api/src/local_user/ban_person.rs @@ -9,6 +9,7 @@ use lemmy_api_common::{ }; use lemmy_db_schema::{ source::{ + local_user::LocalUser, login_token::LoginToken, moderator::{ModBan, ModBanForm}, person::{Person, PersonUpdateForm}, @@ -31,6 +32,14 @@ pub async fn ban_from_site( // Make sure user is an admin is_admin(&local_user_view)?; + // Also make sure you're a higher admin than the target + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + vec![data.person_id], + ) + .await?; + if let Some(reason) = &data.reason { is_valid_body_field(reason, false)?; } diff --git a/crates/api/src/site/purge/comment.rs b/crates/api/src/site/purge/comment.rs index f99dfc689..9f90aff99 100644 --- a/crates/api/src/site/purge/comment.rs +++ b/crates/api/src/site/purge/comment.rs @@ -10,6 +10,7 @@ use lemmy_api_common::{ use lemmy_db_schema::{ source::{ comment::Comment, + local_user::LocalUser, moderator::{AdminPurgeComment, AdminPurgeCommentForm}, }, traits::Crud, @@ -37,6 +38,14 @@ pub async fn purge_comment( .await? .ok_or(LemmyErrorType::CouldntFindComment)?; + // Also check that you're a higher admin + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + vec![comment_view.creator.id], + ) + .await?; + let post_id = comment_view.comment.post_id; // TODO read comments for pictrs images and purge them diff --git a/crates/api/src/site/purge/community.rs b/crates/api/src/site/purge/community.rs index 14b250681..59eded6ad 100644 --- a/crates/api/src/site/purge/community.rs +++ b/crates/api/src/site/purge/community.rs @@ -9,13 +9,16 @@ use lemmy_api_common::{ SuccessResponse, }; use lemmy_db_schema::{ + newtypes::PersonId, source::{ community::Community, + local_user::LocalUser, moderator::{AdminPurgeCommunity, AdminPurgeCommunityForm}, }, traits::Crud, }; use lemmy_db_views::structs::LocalUserView; +use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::{error::LemmyResult, LemmyErrorType}; #[tracing::instrument(skip(context))] @@ -32,6 +35,21 @@ pub async fn purge_community( .await? .ok_or(LemmyErrorType::CouldntFindCommunity)?; + // Also check that you're a higher admin than all the mods + let community_mod_person_ids = + CommunityModeratorView::for_community(&mut context.pool(), community.id) + .await? + .iter() + .map(|cmv| cmv.moderator.id) + .collect::>(); + + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + community_mod_person_ids, + ) + .await?; + if let Some(banner) = &community.banner { purge_image_from_pictrs(banner, &context).await.ok(); } diff --git a/crates/api/src/site/purge/person.rs b/crates/api/src/site/purge/person.rs index 1b38752c7..dc824b163 100644 --- a/crates/api/src/site/purge/person.rs +++ b/crates/api/src/site/purge/person.rs @@ -10,6 +10,7 @@ use lemmy_api_common::{ }; use lemmy_db_schema::{ source::{ + local_user::LocalUser, moderator::{AdminPurgePerson, AdminPurgePersonForm}, person::{Person, PersonUpdateForm}, }, @@ -27,9 +28,18 @@ pub async fn purge_person( // Only let admin purge an item is_admin(&local_user_view)?; + // Also check that you're a higher admin + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + vec![data.person_id], + ) + .await?; + let person = Person::read(&mut context.pool(), data.person_id) .await? .ok_or(LemmyErrorType::CouldntFindPerson)?; + ban_nonlocal_user_from_local_communities( &local_user_view, &person, diff --git a/crates/api/src/site/purge/post.rs b/crates/api/src/site/purge/post.rs index 75cd021d1..6e512312f 100644 --- a/crates/api/src/site/purge/post.rs +++ b/crates/api/src/site/purge/post.rs @@ -10,6 +10,7 @@ use lemmy_api_common::{ }; use lemmy_db_schema::{ source::{ + local_user::LocalUser, moderator::{AdminPurgePost, AdminPurgePostForm}, post::Post, }, @@ -32,6 +33,14 @@ pub async fn purge_post( .await? .ok_or(LemmyErrorType::CouldntFindPost)?; + // Also check that you're a higher admin + LocalUser::is_higher_admin_check( + &mut context.pool(), + local_user_view.person.id, + vec![post.creator_id], + ) + .await?; + // Purge image if let Some(url) = &post.url { purge_image_from_pictrs(url, &context).await.ok(); diff --git a/crates/api_common/src/claims.rs b/crates/api_common/src/claims.rs index 6c17d4e6a..905394785 100644 --- a/crates/api_common/src/claims.rs +++ b/crates/api_common/src/claims.rs @@ -116,10 +116,7 @@ mod tests { let inserted_person = Person::create(pool, &new_person).await.unwrap(); - let local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .password_encrypted("123456".to_string()) - .build(); + let local_user_form = LocalUserInsertForm::test_form(inserted_person.id); let inserted_local_user = LocalUser::create(pool, &local_user_form, vec![]) .await diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index 83ef82e3a..f810c8275 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -11,6 +11,7 @@ use lemmy_db_schema::{ source::{ comment::{Comment, CommentUpdateForm}, comment_report::CommentReport, + local_user::LocalUser, moderator::{ModRemoveComment, ModRemoveCommentForm}, }, traits::{Crud, Reportable}, @@ -41,6 +42,14 @@ pub async fn remove_comment( ) .await?; + LocalUser::is_higher_mod_or_admin_check( + &mut context.pool(), + orig_comment.community.id, + local_user_view.person.id, + vec![orig_comment.creator.id], + ) + .await?; + // Don't allow removing or restoring comment which was deleted by user, as it would reveal // the comment text in mod log. if orig_comment.comment.deleted { diff --git a/crates/api_crud/src/post/remove.rs b/crates/api_crud/src/post/remove.rs index 4ca15c90f..b4fdba6fb 100644 --- a/crates/api_crud/src/post/remove.rs +++ b/crates/api_crud/src/post/remove.rs @@ -9,6 +9,7 @@ use lemmy_api_common::{ }; use lemmy_db_schema::{ source::{ + local_user::LocalUser, moderator::{ModRemovePost, ModRemovePostForm}, post::{Post, PostUpdateForm}, post_report::PostReport, @@ -37,6 +38,14 @@ pub async fn remove_post( ) .await?; + LocalUser::is_higher_mod_or_admin_check( + &mut context.pool(), + orig_post.community_id, + local_user_view.person.id, + vec![orig_post.creator_id], + ) + .await?; + // Update the post let post_id = data.post_id; let removed = data.removed; diff --git a/crates/api_crud/src/user/create.rs b/crates/api_crud/src/user/create.rs index c84bd0a50..64bef8760 100644 --- a/crates/api_crud/src/user/create.rs +++ b/crates/api_crud/src/user/create.rs @@ -150,18 +150,18 @@ pub async fn register( .unwrap_or(site_view.site.content_warning.is_some()); // Create the local user - let local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .email(data.email.as_deref().map(str::to_lowercase)) - .password_encrypted(data.password.to_string()) - .show_nsfw(Some(show_nsfw)) - .accepted_application(accepted_application) - .default_listing_type(Some(local_site.default_post_listing_type)) - .post_listing_mode(Some(local_site.default_post_listing_mode)) - .interface_language(language_tags.first().cloned()) + let local_user_form = LocalUserInsertForm { + email: data.email.as_deref().map(str::to_lowercase), + password_encrypted: data.password.to_string(), + show_nsfw: Some(show_nsfw), + accepted_application, + default_listing_type: Some(local_site.default_post_listing_type), + post_listing_mode: Some(local_site.default_post_listing_mode), + interface_language: language_tags.first().cloned(), // If its the initial site setup, they are an admin - .admin(Some(!local_site.site_setup)) - .build(); + admin: Some(!local_site.site_setup), + ..LocalUserInsertForm::new(inserted_person.id, data.password.to_string()) + }; let all_languages = Language::read_all(&mut context.pool()).await?; // use hashset to avoid duplicates diff --git a/crates/apub/src/api/user_settings_backup.rs b/crates/apub/src/api/user_settings_backup.rs index 9f2cb58c5..a0879b3c9 100644 --- a/crates/apub/src/api/user_settings_backup.rs +++ b/crates/apub/src/api/user_settings_backup.rs @@ -345,10 +345,7 @@ mod tests { }; let person = Person::create(&mut context.pool(), &person_form).await?; - let user_form = LocalUserInsertForm::builder() - .person_id(person.id) - .password_encrypted("pass".to_string()) - .build(); + let user_form = LocalUserInsertForm::test_form(person.id); let local_user = LocalUser::create(&mut context.pool(), &user_form, vec![]).await?; Ok( diff --git a/crates/db_schema/src/impls/actor_language.rs b/crates/db_schema/src/impls/actor_language.rs index 8483d6c20..5a8658baf 100644 --- a/crates/db_schema/src/impls/actor_language.rs +++ b/crates/db_schema/src/impls/actor_language.rs @@ -533,10 +533,7 @@ mod tests { let person_form = PersonInsertForm::test_form(instance.id, "my test person"); let person = Person::create(pool, &person_form).await.unwrap(); - let local_user_form = LocalUserInsertForm::builder() - .person_id(person.id) - .password_encrypted("my_pw".to_string()) - .build(); + let local_user_form = LocalUserInsertForm::test_form(person.id); let local_user = LocalUser::create(pool, &local_user_form, vec![]) .await @@ -645,10 +642,7 @@ mod tests { let person_form = PersonInsertForm::test_form(instance.id, "my test person"); let person = Person::create(pool, &person_form).await.unwrap(); - let local_user_form = LocalUserInsertForm::builder() - .person_id(person.id) - .password_encrypted("my_pw".to_string()) - .build(); + let local_user_form = LocalUserInsertForm::test_form(person.id); let local_user = LocalUser::create(pool, &local_user_form, vec![]) .await .unwrap(); diff --git a/crates/db_schema/src/impls/community.rs b/crates/db_schema/src/impls/community.rs index 6cd90cc66..eaf35a90d 100644 --- a/crates/db_schema/src/impls/community.rs +++ b/crates/db_schema/src/impls/community.rs @@ -1,7 +1,14 @@ use crate::{ diesel::{DecoratableTarget, OptionalExtension}, newtypes::{CommunityId, DbUrl, PersonId}, - schema::{community, community_follower, instance}, + schema::{ + community, + community_follower, + community_moderator, + community_person_ban, + instance, + post, + }, source::{ actor_language::CommunityLanguage, community::{ @@ -42,6 +49,7 @@ use diesel::{ Queryable, }; use diesel_async::RunQueryDsl; +use lemmy_utils::error::{LemmyErrorType, LemmyResult}; #[async_trait] impl Crud for Community { @@ -83,9 +91,8 @@ impl Joinable for CommunityModerator { pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, ) -> Result { - use crate::schema::community_moderator::dsl::community_moderator; let conn = &mut get_conn(pool).await?; - insert_into(community_moderator) + insert_into(community_moderator::table) .values(community_moderator_form) .get_result::(conn) .await @@ -95,9 +102,8 @@ impl Joinable for CommunityModerator { pool: &mut DbPool<'_>, community_moderator_form: &CommunityModeratorForm, ) -> Result { - use crate::schema::community_moderator::dsl::community_moderator; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.find(( + diesel::delete(community_moderator::table.find(( community_moderator_form.person_id, community_moderator_form.community_id, ))) @@ -147,25 +153,23 @@ impl Community { pool: &mut DbPool<'_>, url: &DbUrl, ) -> Result, Error> { - use crate::schema::community::dsl::{featured_url, moderators_url}; - use CollectionType::*; let conn = &mut get_conn(pool).await?; let res = community::table - .filter(moderators_url.eq(url)) + .filter(community::moderators_url.eq(url)) .first(conn) .await .optional()?; if let Some(c) = res { - Ok(Some((c, Moderators))) + Ok(Some((c, CollectionType::Moderators))) } else { let res = community::table - .filter(featured_url.eq(url)) + .filter(community::featured_url.eq(url)) .first(conn) .await .optional()?; if let Some(c) = res { - Ok(Some((c, Featured))) + Ok(Some((c, CollectionType::Featured))) } else { Ok(None) } @@ -177,7 +181,6 @@ impl Community { posts: Vec, pool: &mut DbPool<'_>, ) -> Result<(), Error> { - use crate::schema::post; let conn = &mut get_conn(pool).await?; for p in &posts { debug_assert!(p.community_id == community_id); @@ -185,10 +188,10 @@ impl Community { // Mark the given posts as featured and all other posts as not featured. let post_ids = posts.iter().map(|p| p.id); update(post::table) - .filter(post::dsl::community_id.eq(community_id)) + .filter(post::community_id.eq(community_id)) // This filter is just for performance - .filter(post::dsl::featured_community.or(post::dsl::id.eq_any(post_ids.clone()))) - .set(post::dsl::featured_community.eq(post::dsl::id.eq_any(post_ids))) + .filter(post::featured_community.or(post::id.eq_any(post_ids.clone()))) + .set(post::featured_community.eq(post::id.eq_any(post_ids))) .execute(conn) .await?; Ok(()) @@ -200,37 +203,68 @@ impl CommunityModerator { pool: &mut DbPool<'_>, for_community_id: CommunityId, ) -> Result { - use crate::schema::community_moderator::dsl::{community_id, community_moderator}; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.filter(community_id.eq(for_community_id))) - .execute(conn) - .await + diesel::delete( + community_moderator::table.filter(community_moderator::community_id.eq(for_community_id)), + ) + .execute(conn) + .await } pub async fn leave_all_communities( pool: &mut DbPool<'_>, for_person_id: PersonId, ) -> Result { - use crate::schema::community_moderator::dsl::{community_moderator, person_id}; let conn = &mut get_conn(pool).await?; - diesel::delete(community_moderator.filter(person_id.eq(for_person_id))) - .execute(conn) - .await + diesel::delete( + community_moderator::table.filter(community_moderator::person_id.eq(for_person_id)), + ) + .execute(conn) + .await } pub async fn get_person_moderated_communities( pool: &mut DbPool<'_>, for_person_id: PersonId, ) -> Result, Error> { - use crate::schema::community_moderator::dsl::{community_id, community_moderator, person_id}; let conn = &mut get_conn(pool).await?; - community_moderator - .filter(person_id.eq(for_person_id)) - .select(community_id) + community_moderator::table + .filter(community_moderator::person_id.eq(for_person_id)) + .select(community_moderator::community_id) .load::(conn) .await } + + /// Checks to make sure the acting moderator was added earlier than the target moderator + pub async fn is_higher_mod_check( + pool: &mut DbPool<'_>, + for_community_id: CommunityId, + mod_person_id: PersonId, + target_person_ids: Vec, + ) -> LemmyResult<()> { + let conn = &mut get_conn(pool).await?; + + // Build the list of persons + let mut persons = target_person_ids; + persons.push(mod_person_id); + persons.dedup(); + + let res = community_moderator::table + .filter(community_moderator::community_id.eq(for_community_id)) + .filter(community_moderator::person_id.eq_any(persons)) + .order_by(community_moderator::published) + // This does a limit 1 select first + .first::(conn) + .await?; + + // If the first result sorted by published is the acting mod + if res.person_id == mod_person_id { + Ok(()) + } else { + Err(LemmyErrorType::NotHigherMod)? + } + } } #[async_trait] @@ -240,11 +274,13 @@ impl Bannable for CommunityPersonBan { pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use crate::schema::community_person_ban::dsl::{community_id, community_person_ban, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(community_person_ban) + insert_into(community_person_ban::table) .values(community_person_ban_form) - .on_conflict((community_id, person_id)) + .on_conflict(( + community_person_ban::community_id, + community_person_ban::person_id, + )) .do_update() .set(community_person_ban_form) .get_result::(conn) @@ -255,9 +291,8 @@ impl Bannable for CommunityPersonBan { pool: &mut DbPool<'_>, community_person_ban_form: &CommunityPersonBanForm, ) -> Result { - use crate::schema::community_person_ban::dsl::community_person_ban; let conn = &mut get_conn(pool).await?; - diesel::delete(community_person_ban.find(( + diesel::delete(community_person_ban::table.find(( community_person_ban_form.person_id, community_person_ban_form.community_id, ))) @@ -291,11 +326,10 @@ impl CommunityFollower { pool: &mut DbPool<'_>, remote_community_id: CommunityId, ) -> Result { - use crate::schema::community_follower::dsl::{community_follower, community_id}; let conn = &mut get_conn(pool).await?; - select(exists( - community_follower.filter(community_id.eq(remote_community_id)), - )) + select(exists(community_follower::table.filter( + community_follower::community_id.eq(remote_community_id), + ))) .get_result(conn) .await } @@ -316,11 +350,13 @@ impl Queryable, Pg> for SubscribedType { impl Followable for CommunityFollower { type Form = CommunityFollowerForm; async fn follow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { - use crate::schema::community_follower::dsl::{community_follower, community_id, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(community_follower) + insert_into(community_follower::table) .values(form) - .on_conflict((community_id, person_id)) + .on_conflict(( + community_follower::community_id, + community_follower::person_id, + )) .do_update() .set(form) .get_result::(conn) @@ -331,17 +367,16 @@ impl Followable for CommunityFollower { community_id: CommunityId, person_id: PersonId, ) -> Result { - use crate::schema::community_follower::dsl::{community_follower, pending}; let conn = &mut get_conn(pool).await?; - diesel::update(community_follower.find((person_id, community_id))) - .set(pending.eq(false)) + diesel::update(community_follower::table.find((person_id, community_id))) + .set(community_follower::pending.eq(false)) .get_result::(conn) .await } + async fn unfollow(pool: &mut DbPool<'_>, form: &CommunityFollowerForm) -> Result { - use crate::schema::community_follower::dsl::community_follower; let conn = &mut get_conn(pool).await?; - diesel::delete(community_follower.find((form.person_id, form.community_id))) + diesel::delete(community_follower::table.find((form.person_id, form.community_id))) .execute(conn) .await } @@ -397,10 +432,8 @@ impl ApubActor for Community { } #[cfg(test)] -#[allow(clippy::unwrap_used)] #[allow(clippy::indexing_slicing)] mod tests { - use crate::{ source::{ community::{ @@ -415,28 +448,30 @@ mod tests { CommunityUpdateForm, }, instance::Instance, + local_user::LocalUser, person::{Person, PersonInsertForm}, }, traits::{Bannable, Crud, Followable, Joinable}, utils::build_db_pool_for_tests, CommunityVisibility, }; + use lemmy_utils::{error::LemmyResult, LemmyErrorType}; use pretty_assertions::assert_eq; use serial_test::serial; #[tokio::test] #[serial] - async fn test_crud() { + async fn test_crud() -> LemmyResult<()> { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); - let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) - .await - .unwrap(); + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?; - let new_person = PersonInsertForm::test_form(inserted_instance.id, "bobbee"); + let bobby_person = PersonInsertForm::test_form(inserted_instance.id, "bobby"); + let inserted_bobby = Person::create(pool, &bobby_person).await?; - let inserted_person = Person::create(pool, &new_person).await.unwrap(); + let artemis_person = PersonInsertForm::test_form(inserted_instance.id, "artemis"); + let inserted_artemis = Person::create(pool, &artemis_person).await?; let new_community = CommunityInsertForm::builder() .name("TIL".into()) @@ -445,7 +480,7 @@ mod tests { .instance_id(inserted_instance.id) .build(); - let inserted_community = Community::create(pool, &new_community).await.unwrap(); + let inserted_community = Community::create(pool, &new_community).await?; let expected_community = Community { id: inserted_community.id, @@ -477,91 +512,120 @@ mod tests { let community_follower_form = CommunityFollowerForm { community_id: inserted_community.id, - person_id: inserted_person.id, + person_id: inserted_bobby.id, pending: false, }; - let inserted_community_follower = CommunityFollower::follow(pool, &community_follower_form) - .await - .unwrap(); + let inserted_community_follower = + CommunityFollower::follow(pool, &community_follower_form).await?; let expected_community_follower = CommunityFollower { community_id: inserted_community.id, - person_id: inserted_person.id, + person_id: inserted_bobby.id, pending: false, published: inserted_community_follower.published, }; - let community_moderator_form = CommunityModeratorForm { + let bobby_moderator_form = CommunityModeratorForm { community_id: inserted_community.id, - person_id: inserted_person.id, + person_id: inserted_bobby.id, }; - let inserted_community_moderator = CommunityModerator::join(pool, &community_moderator_form) - .await - .unwrap(); + let inserted_bobby_moderator = CommunityModerator::join(pool, &bobby_moderator_form).await?; + + let artemis_moderator_form = CommunityModeratorForm { + community_id: inserted_community.id, + person_id: inserted_artemis.id, + }; + + let _inserted_artemis_moderator = + CommunityModerator::join(pool, &artemis_moderator_form).await?; let expected_community_moderator = CommunityModerator { community_id: inserted_community.id, - person_id: inserted_person.id, - published: inserted_community_moderator.published, + person_id: inserted_bobby.id, + published: inserted_bobby_moderator.published, }; + let moderator_person_ids = vec![inserted_bobby.id, inserted_artemis.id]; + + // Make sure bobby is marked as a higher mod than artemis, and vice versa + let bobby_higher_check = CommunityModerator::is_higher_mod_check( + pool, + inserted_community.id, + inserted_bobby.id, + moderator_person_ids.clone(), + ) + .await; + assert!(bobby_higher_check.is_ok()); + + // Also check the other is_higher_mod_or_admin function just in case + let bobby_higher_check_2 = LocalUser::is_higher_mod_or_admin_check( + pool, + inserted_community.id, + inserted_bobby.id, + moderator_person_ids.clone(), + ) + .await; + assert!(bobby_higher_check_2.is_ok()); + + // This should throw an error, since artemis was added later + let artemis_higher_check = CommunityModerator::is_higher_mod_check( + pool, + inserted_community.id, + inserted_artemis.id, + moderator_person_ids, + ) + .await; + assert!(artemis_higher_check.is_err()); + let community_person_ban_form = CommunityPersonBanForm { community_id: inserted_community.id, - person_id: inserted_person.id, + person_id: inserted_bobby.id, expires: None, }; - let inserted_community_person_ban = CommunityPersonBan::ban(pool, &community_person_ban_form) - .await - .unwrap(); + let inserted_community_person_ban = + CommunityPersonBan::ban(pool, &community_person_ban_form).await?; let expected_community_person_ban = CommunityPersonBan { community_id: inserted_community.id, - person_id: inserted_person.id, + person_id: inserted_bobby.id, published: inserted_community_person_ban.published, expires: None, }; let read_community = Community::read(pool, inserted_community.id) - .await - .unwrap() - .unwrap(); + .await? + .ok_or(LemmyErrorType::CouldntFindCommunity)?; 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(); + let updated_community = + Community::update(pool, inserted_community.id, &update_community_form).await?; - let ignored_community = CommunityFollower::unfollow(pool, &community_follower_form) - .await - .unwrap(); - let left_community = CommunityModerator::leave(pool, &community_moderator_form) - .await - .unwrap(); - let unban = CommunityPersonBan::unban(pool, &community_person_ban_form) - .await - .unwrap(); - let num_deleted = Community::delete(pool, inserted_community.id) - .await - .unwrap(); - Person::delete(pool, inserted_person.id).await.unwrap(); - Instance::delete(pool, inserted_instance.id).await.unwrap(); + let ignored_community = CommunityFollower::unfollow(pool, &community_follower_form).await?; + let left_community = CommunityModerator::leave(pool, &bobby_moderator_form).await?; + let unban = CommunityPersonBan::unban(pool, &community_person_ban_form).await?; + let num_deleted = Community::delete(pool, inserted_community.id).await?; + Person::delete(pool, inserted_bobby.id).await?; + Person::delete(pool, inserted_artemis.id).await?; + Instance::delete(pool, inserted_instance.id).await?; assert_eq!(expected_community, read_community); assert_eq!(expected_community, inserted_community); assert_eq!(expected_community, updated_community); assert_eq!(expected_community_follower, inserted_community_follower); - assert_eq!(expected_community_moderator, inserted_community_moderator); + assert_eq!(expected_community_moderator, inserted_bobby_moderator); assert_eq!(expected_community_person_ban, inserted_community_person_ban); assert_eq!(1, ignored_community); assert_eq!(1, left_community); assert_eq!(1, unban); // assert_eq!(2, loaded_count); assert_eq!(1, num_deleted); + + Ok(()) } } diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 694979ade..32e8d50b7 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -1,6 +1,6 @@ use crate::{ - newtypes::{DbUrl, LanguageId, LocalUserId, PersonId}, - schema::{community, local_user, person, registration_application}, + newtypes::{CommunityId, DbUrl, LanguageId, LocalUserId, PersonId}, + schema::{community, community_moderator, local_user, person, registration_application}, source::{ actor_language::LocalUserLanguage, local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm}, @@ -19,11 +19,13 @@ use bcrypt::{hash, DEFAULT_COST}; use diesel::{ dsl::{insert_into, not, IntervalDsl}, result::Error, + CombineDsl, ExpressionMethods, JoinOnDsl, QueryDsl, }; use diesel_async::RunQueryDsl; +use lemmy_utils::error::{LemmyErrorType, LemmyResult}; impl LocalUser { pub async fn create( @@ -216,6 +218,72 @@ impl LocalUser { blocked_instances, }) } + + /// Checks to make sure the acting admin is higher than the target admin + pub async fn is_higher_admin_check( + pool: &mut DbPool<'_>, + admin_person_id: PersonId, + target_person_ids: Vec, + ) -> LemmyResult<()> { + let conn = &mut get_conn(pool).await?; + + // Build the list of persons + let mut persons = target_person_ids; + persons.push(admin_person_id); + persons.dedup(); + + let res = local_user::table + .filter(local_user::admin.eq(true)) + .filter(local_user::person_id.eq_any(persons)) + .order_by(local_user::id) + // This does a limit 1 select first + .first::(conn) + .await?; + + // If the first result sorted by published is the acting admin + if res.person_id == admin_person_id { + Ok(()) + } else { + Err(LemmyErrorType::NotHigherAdmin)? + } + } + + /// Checks to make sure the acting moderator is higher than the target moderator + pub async fn is_higher_mod_or_admin_check( + pool: &mut DbPool<'_>, + for_community_id: CommunityId, + admin_person_id: PersonId, + target_person_ids: Vec, + ) -> LemmyResult<()> { + let conn = &mut get_conn(pool).await?; + + // Build the list of persons + let mut persons = target_person_ids; + persons.push(admin_person_id); + persons.dedup(); + + let admins = local_user::table + .filter(local_user::admin.eq(true)) + .filter(local_user::person_id.eq_any(&persons)) + .order_by(local_user::id) + .select(local_user::person_id); + + let mods = community_moderator::table + .filter(community_moderator::community_id.eq(for_community_id)) + .filter(community_moderator::person_id.eq_any(&persons)) + .order_by(community_moderator::published) + .select(community_moderator::person_id); + + let res = admins.union_all(mods).get_results::(conn).await?; + let first_person = res.as_slice().first().ok_or(LemmyErrorType::NotHigherMod)?; + + // If the first result sorted by published is the acting mod + if *first_person == admin_person_id { + Ok(()) + } else { + Err(LemmyErrorType::NotHigherMod)? + } + } } /// Adds some helper functions for an optional LocalUser @@ -278,10 +346,14 @@ impl LocalUserOptionHelper for Option<&LocalUser> { impl LocalUserInsertForm { pub fn test_form(person_id: PersonId) -> Self { - Self::builder() - .person_id(person_id) - .password_encrypted(String::new()) - .build() + Self::new(person_id, String::new()) + } + + pub fn test_form_admin(person_id: PersonId) -> Self { + LocalUserInsertForm { + admin: Some(true), + ..Self::test_form(person_id) + } } } @@ -293,3 +365,58 @@ pub struct UserBackupLists { pub blocked_users: Vec, pub blocked_instances: Vec, } + +#[cfg(test)] +#[allow(clippy::indexing_slicing)] +mod tests { + use crate::{ + source::{ + instance::Instance, + local_user::{LocalUser, LocalUserInsertForm}, + person::{Person, PersonInsertForm}, + }, + traits::Crud, + utils::build_db_pool_for_tests, + }; + use lemmy_utils::error::LemmyResult; + use serial_test::serial; + + #[tokio::test] + #[serial] + async fn test_admin_higher_check() -> LemmyResult<()> { + let pool = &build_db_pool_for_tests().await; + let pool = &mut pool.into(); + + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?; + + let fiona_person = PersonInsertForm::test_form(inserted_instance.id, "fiona"); + let inserted_fiona_person = Person::create(pool, &fiona_person).await?; + + let fiona_local_user_form = LocalUserInsertForm::test_form_admin(inserted_fiona_person.id); + let _inserted_fiona_local_user = + LocalUser::create(pool, &fiona_local_user_form, vec![]).await?; + + let delores_person = PersonInsertForm::test_form(inserted_instance.id, "delores"); + let inserted_delores_person = Person::create(pool, &delores_person).await?; + let delores_local_user_form = LocalUserInsertForm::test_form_admin(inserted_delores_person.id); + let _inserted_delores_local_user = + LocalUser::create(pool, &delores_local_user_form, vec![]).await?; + + let admin_person_ids = vec![inserted_fiona_person.id, inserted_delores_person.id]; + + // Make sure fiona is marked as a higher admin than delores, and vice versa + let fiona_higher_check = + LocalUser::is_higher_admin_check(pool, inserted_fiona_person.id, admin_person_ids.clone()) + .await; + assert!(fiona_higher_check.is_ok()); + + // This should throw an error, since delores was added later + let delores_higher_check = + LocalUser::is_higher_admin_check(pool, inserted_delores_person.id, admin_person_ids).await; + assert!(delores_higher_check.is_err()); + + Instance::delete(pool, inserted_instance.id).await?; + + Ok(()) + } +} diff --git a/crates/db_schema/src/impls/password_reset_request.rs b/crates/db_schema/src/impls/password_reset_request.rs index 0b1351af1..be05ed8ac 100644 --- a/crates/db_schema/src/impls/password_reset_request.rs +++ b/crates/db_schema/src/impls/password_reset_request.rs @@ -72,10 +72,7 @@ mod tests { let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?; let new_person = PersonInsertForm::test_form(inserted_instance.id, "thommy prw"); let inserted_person = Person::create(pool, &new_person).await?; - let new_local_user = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .password_encrypted("pass".to_string()) - .build(); + let new_local_user = LocalUserInsertForm::test_form(inserted_person.id); let inserted_local_user = LocalUser::create(pool, &new_local_user, vec![]).await?; // Create password reset token diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index f318a503a..89c108f8c 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -182,11 +182,10 @@ impl ApubActor for Person { impl Followable for PersonFollower { type Form = PersonFollowerForm; async fn follow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { - use crate::schema::person_follower::dsl::{follower_id, person_follower, person_id}; let conn = &mut get_conn(pool).await?; - insert_into(person_follower) + insert_into(person_follower::table) .values(form) - .on_conflict((follower_id, person_id)) + .on_conflict((person_follower::follower_id, person_follower::person_id)) .do_update() .set(form) .get_result::(conn) @@ -196,9 +195,8 @@ impl Followable for PersonFollower { unimplemented!() } async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { - use crate::schema::person_follower::dsl::person_follower; let conn = &mut get_conn(pool).await?; - diesel::delete(person_follower.find((form.follower_id, form.person_id))) + diesel::delete(person_follower::table.find((form.follower_id, form.person_id))) .execute(conn) .await } @@ -220,7 +218,6 @@ impl PersonFollower { } #[cfg(test)] -#[allow(clippy::unwrap_used)] #[allow(clippy::indexing_slicing)] mod tests { @@ -232,22 +229,21 @@ mod tests { traits::{Crud, Followable}, utils::build_db_pool_for_tests, }; + use lemmy_utils::{error::LemmyResult, LemmyErrorType}; use pretty_assertions::assert_eq; use serial_test::serial; #[tokio::test] #[serial] - async fn test_crud() { + async fn test_crud() -> LemmyResult<()> { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); - let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) - .await - .unwrap(); + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?; let new_person = PersonInsertForm::test_form(inserted_instance.id, "holly"); - let inserted_person = Person::create(pool, &new_person).await.unwrap(); + let inserted_person = Person::create(pool, &new_person).await?; let expected_person = Person { id: inserted_person.id, @@ -274,57 +270,54 @@ mod tests { }; let read_person = Person::read(pool, inserted_person.id) - .await - .unwrap() - .unwrap(); + .await? + .ok_or(LemmyErrorType::CouldntFindPerson)?; 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(); + let updated_person = Person::update(pool, inserted_person.id, &update_person_form).await?; - let num_deleted = Person::delete(pool, inserted_person.id).await.unwrap(); - Instance::delete(pool, inserted_instance.id).await.unwrap(); + let num_deleted = Person::delete(pool, inserted_person.id).await?; + Instance::delete(pool, inserted_instance.id).await?; assert_eq!(expected_person, read_person); assert_eq!(expected_person, inserted_person); assert_eq!(expected_person, updated_person); assert_eq!(1, num_deleted); + + Ok(()) } #[tokio::test] #[serial] - async fn follow() { + async fn follow() -> LemmyResult<()> { let pool = &build_db_pool_for_tests().await; let pool = &mut pool.into(); - let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) - .await - .unwrap(); + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()).await?; let person_form_1 = PersonInsertForm::test_form(inserted_instance.id, "erich"); - let person_1 = Person::create(pool, &person_form_1).await.unwrap(); + let person_1 = Person::create(pool, &person_form_1).await?; let person_form_2 = PersonInsertForm::test_form(inserted_instance.id, "michele"); - let person_2 = Person::create(pool, &person_form_2).await.unwrap(); + let person_2 = Person::create(pool, &person_form_2).await?; let follow_form = PersonFollowerForm { person_id: person_1.id, follower_id: person_2.id, pending: false, }; - let person_follower = PersonFollower::follow(pool, &follow_form).await.unwrap(); + let person_follower = PersonFollower::follow(pool, &follow_form).await?; assert_eq!(person_1.id, person_follower.person_id); assert_eq!(person_2.id, person_follower.follower_id); assert!(!person_follower.pending); - let followers = PersonFollower::list_followers(pool, person_1.id) - .await - .unwrap(); + let followers = PersonFollower::list_followers(pool, person_1.id).await?; assert_eq!(vec![person_2], followers); - let unfollow = PersonFollower::unfollow(pool, &follow_form).await.unwrap(); + let unfollow = PersonFollower::unfollow(pool, &follow_form).await?; assert_eq!(1, unfollow); + + Ok(()) } } diff --git a/crates/db_schema/src/source/local_user.rs b/crates/db_schema/src/source/local_user.rs index 5d592ddf1..c7a5b5224 100644 --- a/crates/db_schema/src/source/local_user.rs +++ b/crates/db_schema/src/source/local_user.rs @@ -11,7 +11,6 @@ use serde::{Deserialize, Serialize}; use serde_with::skip_serializing_none; #[cfg(feature = "full")] use ts_rs::TS; -use typed_builder::TypedBuilder; #[skip_serializing_none] #[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)] @@ -69,38 +68,59 @@ pub struct LocalUser { pub collapse_bot_comments: bool, } -#[derive(Clone, TypedBuilder)] -#[builder(field_defaults(default))] +#[derive(Clone, derive_new::new)] #[cfg_attr(feature = "full", derive(Insertable))] #[cfg_attr(feature = "full", diesel(table_name = local_user))] pub struct LocalUserInsertForm { - #[builder(!default)] pub person_id: PersonId, - #[builder(!default)] pub password_encrypted: String, + #[new(default)] pub email: Option, + #[new(default)] pub show_nsfw: Option, + #[new(default)] pub theme: Option, + #[new(default)] pub default_sort_type: Option, + #[new(default)] pub default_listing_type: Option, + #[new(default)] pub interface_language: Option, + #[new(default)] pub show_avatars: Option, + #[new(default)] pub send_notifications_to_email: Option, + #[new(default)] pub show_bot_accounts: Option, + #[new(default)] pub show_scores: Option, + #[new(default)] pub show_read_posts: Option, + #[new(default)] pub email_verified: Option, + #[new(default)] pub accepted_application: Option, + #[new(default)] pub totp_2fa_secret: Option>, + #[new(default)] pub open_links_in_new_tab: Option, + #[new(default)] pub blur_nsfw: Option, + #[new(default)] pub auto_expand: Option, + #[new(default)] pub infinite_scroll_enabled: Option, + #[new(default)] pub admin: Option, + #[new(default)] pub post_listing_mode: Option, + #[new(default)] pub totp_2fa_enabled: Option, + #[new(default)] pub enable_keyboard_navigation: Option, + #[new(default)] pub enable_animated_images: Option, + #[new(default)] pub collapse_bot_comments: Option, } diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index 950d061ba..d7b26a1ed 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -301,10 +301,7 @@ mod tests { let inserted_timmy = Person::create(pool, &new_person).await.unwrap(); - let new_local_user = LocalUserInsertForm::builder() - .person_id(inserted_timmy.id) - .password_encrypted("123".to_string()) - .build(); + let new_local_user = LocalUserInsertForm::test_form(inserted_timmy.id); let timmy_local_user = LocalUser::create(pool, &new_local_user, vec![]) .await .unwrap(); diff --git a/crates/db_views/src/comment_view.rs b/crates/db_views/src/comment_view.rs index 0e476b3b6..e2752a0c7 100644 --- a/crates/db_views/src/comment_view.rs +++ b/crates/db_views/src/comment_view.rs @@ -484,11 +484,8 @@ mod tests { let timmy_person_form = PersonInsertForm::test_form(inserted_instance.id, "timmy"); let inserted_timmy_person = Person::create(pool, &timmy_person_form).await?; - let timmy_local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_timmy_person.id) - .admin(Some(true)) - .password_encrypted(String::new()) - .build(); + let timmy_local_user_form = LocalUserInsertForm::test_form_admin(inserted_timmy_person.id); + let inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form, vec![]).await?; let sara_person_form = PersonInsertForm::test_form(inserted_instance.id, "sara"); diff --git a/crates/db_views/src/post_report_view.rs b/crates/db_views/src/post_report_view.rs index e89b7d545..0cd06dd4e 100644 --- a/crates/db_views/src/post_report_view.rs +++ b/crates/db_views/src/post_report_view.rs @@ -323,10 +323,7 @@ mod tests { let inserted_timmy = Person::create(pool, &new_person).await.unwrap(); - let new_local_user = LocalUserInsertForm::builder() - .person_id(inserted_timmy.id) - .password_encrypted("123".to_string()) - .build(); + let new_local_user = LocalUserInsertForm::test_form(inserted_timmy.id); let timmy_local_user = LocalUser::create(pool, &new_local_user, vec![]) .await .unwrap(); diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs index cd63859af..9a85d534a 100644 --- a/crates/db_views/src/registration_application_view.rs +++ b/crates/db_views/src/registration_application_view.rs @@ -167,11 +167,7 @@ mod tests { let inserted_timmy_person = Person::create(pool, &timmy_person_form).await.unwrap(); - let timmy_local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_timmy_person.id) - .password_encrypted("nada".to_string()) - .admin(Some(true)) - .build(); + let timmy_local_user_form = LocalUserInsertForm::test_form_admin(inserted_timmy_person.id); let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form, vec![]) .await @@ -181,10 +177,7 @@ mod tests { let inserted_sara_person = Person::create(pool, &sara_person_form).await.unwrap(); - let sara_local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_sara_person.id) - .password_encrypted("nada".to_string()) - .build(); + let sara_local_user_form = LocalUserInsertForm::test_form(inserted_sara_person.id); let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form, vec![]) .await @@ -209,10 +202,7 @@ mod tests { let inserted_jess_person = Person::create(pool, &jess_person_form).await.unwrap(); - let jess_local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_jess_person.id) - .password_encrypted("nada".to_string()) - .build(); + let jess_local_user_form = LocalUserInsertForm::test_form(inserted_jess_person.id); let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form, vec![]) .await diff --git a/crates/db_views_actor/src/community_view.rs b/crates/db_views_actor/src/community_view.rs index 7d8a7277f..0e731878a 100644 --- a/crates/db_views_actor/src/community_view.rs +++ b/crates/db_views_actor/src/community_view.rs @@ -275,10 +275,7 @@ mod tests { let inserted_person = Person::create(pool, &new_person).await.unwrap(); - let local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .password_encrypted(String::new()) - .build(); + let local_user_form = LocalUserInsertForm::test_form(inserted_person.id); let local_user = LocalUser::create(pool, &local_user_form, vec![]) .await .unwrap(); diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 98a0ca38d..26e4ee680 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -196,10 +196,7 @@ mod tests { ..PersonInsertForm::test_form(inserted_instance.id, "alice") }; let alice = Person::create(pool, &alice_form).await?; - let alice_local_user_form = LocalUserInsertForm::builder() - .person_id(alice.id) - .password_encrypted(String::new()) - .build(); + let alice_local_user_form = LocalUserInsertForm::test_form(alice.id); let alice_local_user = LocalUser::create(pool, &alice_local_user_form, vec![]).await?; let bob_form = PersonInsertForm { @@ -208,10 +205,7 @@ mod tests { ..PersonInsertForm::test_form(inserted_instance.id, "bob") }; let bob = Person::create(pool, &bob_form).await?; - let bob_local_user_form = LocalUserInsertForm::builder() - .person_id(bob.id) - .password_encrypted(String::new()) - .build(); + let bob_local_user_form = LocalUserInsertForm::test_form(bob.id); let bob_local_user = LocalUser::create(pool, &bob_local_user_form, vec![]).await?; Ok(Data { diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index 324c08ccb..b848916b2 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -38,6 +38,8 @@ pub enum LemmyErrorType { NotTopAdmin, NotTopMod, NotLoggedIn, + NotHigherMod, + NotHigherAdmin, SiteBan, Deleted, BannedFromCommunity, diff --git a/src/code_migrations.rs b/src/code_migrations.rs index fd4ef66de..ae6155bb6 100644 --- a/src/code_migrations.rs +++ b/src/code_migrations.rs @@ -468,12 +468,11 @@ async fn initialize_local_site_2022_10_10( }; let person_inserted = Person::create(pool, &person_form).await?; - let local_user_form = LocalUserInsertForm::builder() - .person_id(person_inserted.id) - .password_encrypted(setup.admin_password.clone()) - .email(setup.admin_email.clone()) - .admin(Some(true)) - .build(); + let local_user_form = LocalUserInsertForm { + email: setup.admin_email.clone(), + admin: Some(true), + ..LocalUserInsertForm::new(person_inserted.id, setup.admin_password.clone()) + }; LocalUser::create(pool, &local_user_form, vec![]).await?; }; diff --git a/src/session_middleware.rs b/src/session_middleware.rs index 8b3090a47..a72d84920 100644 --- a/src/session_middleware.rs +++ b/src/session_middleware.rs @@ -146,10 +146,7 @@ mod tests { let inserted_person = Person::create(pool, &new_person).await.unwrap(); - let local_user_form = LocalUserInsertForm::builder() - .person_id(inserted_person.id) - .password_encrypted("123456".to_string()) - .build(); + let local_user_form = LocalUserInsertForm::test_form(inserted_person.id); let inserted_local_user = LocalUser::create(pool, &local_user_form, vec![]) .await From 8abbd564009bfc52dbde218751f3964c10213702 Mon Sep 17 00:00:00 2001 From: Daniel Lo Nigro Date: Wed, 17 Jul 2024 00:59:21 -0700 Subject: [PATCH 17/69] Switch PostgreSQL container to use pgautoupgrade (#4892) * Switch PostgreSQL container to use pgautoupgrade This handles automatically upgrading the data files to newer versions of PostgreSQL. * Fixing other uses of postgres:16-alpine image. * Simplifying upgrade scripts. --------- Co-authored-by: Dessalines --- .woodpecker.yml | 2 +- docker/docker-compose.yml | 2 +- docker/federation/docker-compose.yml | 2 +- scripts/postgres_12_to_15_upgrade.sh | 44 ++-------------------------- scripts/postgres_15_to_16_upgrade.sh | 40 ++----------------------- 5 files changed, 8 insertions(+), 82 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index b77fd6615..fe11411d8 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -306,7 +306,7 @@ steps: services: database: - image: postgres:16-alpine + image: pgautoupgrade/pgautoupgrade:16-alpine environment: POSTGRES_USER: lemmy POSTGRES_PASSWORD: password diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index 655182e1a..c1d8d359b 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -97,7 +97,7 @@ services: logging: *default-logging postgres: - image: postgres:16-alpine + image: pgautoupgrade/pgautoupgrade:16-alpine # this needs to match the database host in lemmy.hson # Tune your settings via # https://pgtune.leopard.in.ua/#/ diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 72a8145ec..2befc78c5 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -20,7 +20,7 @@ x-lemmy-default: &lemmy-default restart: always x-postgres-default: &postgres-default - image: postgres:16-alpine + image: pgautoupgrade/pgautoupgrade:16-alpine environment: - POSTGRES_USER=lemmy - POSTGRES_PASSWORD=password diff --git a/scripts/postgres_12_to_15_upgrade.sh b/scripts/postgres_12_to_15_upgrade.sh index 0850e8fca..9af9af64e 100755 --- a/scripts/postgres_12_to_15_upgrade.sh +++ b/scripts/postgres_12_to_15_upgrade.sh @@ -1,48 +1,8 @@ #!/bin/sh set -e -echo "Do not stop in the middle of this upgrade, wait until you see the message: Upgrade complete." - -echo "Stopping lemmy and all services..." -sudo docker-compose stop - -echo "Make sure postgres is started..." -sudo docker-compose up -d postgres -sleep 20s - -echo "Exporting the Database to 12_15.dump.sql ..." -sudo docker-compose exec -T postgres pg_dumpall -c -U lemmy > 12_15_dump.sql -echo "Done." - -echo "Stopping postgres..." -sudo docker-compose stop postgres -sleep 20s - -echo "Removing the old postgres folder" -sudo rm -rf volumes/postgres - -echo "Updating docker-compose to use postgres version 15." -sed -i "s/image: postgres:.*/image: postgres:15-alpine/" ./docker-compose.yml - -echo "Starting up new postgres..." -sudo docker-compose up -d postgres -sleep 20s - -echo "Importing the database...." -cat 12_15_dump.sql | sudo docker-compose exec -T postgres psql -U lemmy -echo "Done." - -POSTGRES_PASSWORD=$(grep "POSTGRES_PASSWORD" ./docker-compose.yml | cut -d"=" -f2) - -echo "Fixing a weird password issue with postgres 15" -sudo docker-compose exec -T postgres psql -U lemmy -c "alter user lemmy with password '$POSTGRES_PASSWORD'" -sudo docker-compose restart postgres - -echo "Setting correct perms for pictrs folder" -sudo chown -R 991:991 volumes/pictrs +echo "Updating docker-compose to use postgres version 16." +sudo sed -i "s/image: .*postgres:.*/image: pgautoupgrade\/pgautoupgrade:16-alpine/" ./docker-compose.yml echo "Starting up lemmy..." sudo docker-compose up -d - -echo "A copy of your old database is at 12_15.dump.sql . You can delete this file if the upgrade went smoothly." -echo "Upgrade complete." diff --git a/scripts/postgres_15_to_16_upgrade.sh b/scripts/postgres_15_to_16_upgrade.sh index d83803a4f..9af9af64e 100755 --- a/scripts/postgres_15_to_16_upgrade.sh +++ b/scripts/postgres_15_to_16_upgrade.sh @@ -1,42 +1,8 @@ #!/bin/sh set -e -echo "Do not stop in the middle of this upgrade, wait until you see the message: Upgrade complete." - -echo "Stopping lemmy and all services..." -sudo docker compose stop - -echo "Make sure postgres is started..." -sudo docker compose up -d postgres -echo "Waiting..." -sleep 20s - -echo "Exporting the Database to 15_16.dump.sql ..." -sudo docker compose exec -T postgres pg_dumpall -c -U lemmy | sudo tee 15_16_dump.sql > /dev/null -echo "Done." - -echo "Stopping postgres..." -sudo docker compose stop postgres -echo "Waiting..." -sleep 20s - -echo "Removing the old postgres folder" -sudo rm -rf volumes/postgres - -echo "Updating docker compose to use postgres version 16." -sudo sed -i "s/image: .*postgres:.*/image: docker.io\/postgres:16-alpine/" ./docker-compose.yml - -echo "Starting up new postgres..." -sudo docker compose up -d postgres -echo "Waiting..." -sleep 20s - -echo "Importing the database...." -sudo cat 15_16_dump.sql | sudo docker compose exec -T postgres psql -U lemmy -echo "Done." +echo "Updating docker-compose to use postgres version 16." +sudo sed -i "s/image: .*postgres:.*/image: pgautoupgrade\/pgautoupgrade:16-alpine/" ./docker-compose.yml echo "Starting up lemmy..." -sudo docker compose up -d - -echo "A copy of your old database is at 15_16.dump.sql . You can delete this file if the upgrade went smoothly." -echo "Upgrade complete." +sudo docker-compose up -d From 847c01f3483eeb388ad8bc53f6ef173d41ddce26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=97=8D+85CD?= <50108258+kwaa@users.noreply.github.com> Date: Thu, 18 Jul 2024 20:40:43 +0800 Subject: [PATCH 18/69] refactor!: use rustls instead of native-tls (#4901) * refactor(utils): remove apub * refactor(utils): remove apub * refactor(utils): remove openssl * refactor(utils): remove openssl * Use rustls instead of native-tls. * refactor(utils): remove apub * refactor(utils): remove apub * refactor(utils): remove openssl * refactor(utils): remove openssl * Use rustls instead of native-tls. * Upping activitypub_federation dep * Using git dep of webmention. --------- Co-authored-by: Dessalines --- Cargo.lock | 661 +++++------------- Cargo.toml | 9 +- crates/api_crud/Cargo.toml | 2 +- .../src/impls/local_user_vote_display_mode.rs | 1 + crates/utils/Cargo.toml | 8 +- crates/utils/src/apub.rs | 26 - crates/utils/src/lib.rs | 1 - 7 files changed, 204 insertions(+), 504 deletions(-) delete mode 100644 crates/utils/src/apub.rs diff --git a/Cargo.lock b/Cargo.lock index e02388f0c..728eb21ba 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -16,9 +16,9 @@ checksum = "8f27d075294830fcab6f66e320dab524bc6d048f4a151698e153205559113772" [[package]] name = "activitypub_federation" -version = "0.5.6" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8ff2d0151ce9ac02eb29e4a58b41d28693f141f7963d4bfabd2f9d402ecec7" +checksum = "b86eea7a032da501fe07b04a83c10716ea732c45e6943d7f045bc053aca03f2a" dependencies = [ "activitystreams-kinds", "actix-web", @@ -35,14 +35,15 @@ dependencies = [ "http-signature-normalization", "http-signature-normalization-reqwest", "httpdate", - "itertools 0.12.1", + "itertools 0.13.0", "moka", "once_cell", - "openssl", "pin-project-lite", + "rand", "regex", "reqwest 0.11.27", "reqwest-middleware 0.2.5", + "rsa", "serde", "serde_json", "sha2", @@ -266,9 +267,9 @@ dependencies = [ [[package]] name = "actix-web" -version = "4.7.0" +version = "4.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6316df3fa569627c98b12557a8b6ff0674e5be4bb9b5e4ae2550ddb4964ed6" +checksum = "1988c02af8d2b718c05bc4aeb6a66395b7cdf32858c2c71131e5637a8c05a9ff" dependencies = [ "actix-codec", "actix-http", @@ -542,9 +543,9 @@ dependencies = [ [[package]] name = "async-trait" -version = "0.1.80" +version = "0.1.81" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6fa2087f2753a7da8cc1c0dbfcf89579dd57458e36769de5ac750b4671737ca" +checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", @@ -870,9 +871,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "514de17de45fdb8dc022b1a7975556c53c86f9f0aa5f534b98977b171857c2c9" +checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" [[package]] name = "bytestring" @@ -1635,6 +1636,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", + "const-oid", "crypto-common", "subtle", ] @@ -1648,17 +1650,6 @@ dependencies = [ "chrono", ] -[[package]] -name = "displaydoc" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "doku" version = "0.21.1" @@ -1900,21 +1891,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foreign-types" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" -dependencies = [ - "foreign-types-shared", -] - -[[package]] -name = "foreign-types-shared" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" - [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2201,17 +2177,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "hostname" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f9c7c7c8ac16c798734b8a24560c1362120597c40d5e1459f09498f8f6c8f2ba" -dependencies = [ - "cfg-if", - "libc", - "windows", -] - [[package]] name = "hound" version = "3.5.1" @@ -2427,6 +2392,20 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" +dependencies = [ + "futures-util", + "http 0.2.12", + "hyper 0.14.29", + "rustls 0.21.12", + "tokio", + "tokio-rustls 0.24.1", +] + [[package]] name = "hyper-rustls" version = "0.26.0" @@ -2456,19 +2435,6 @@ dependencies = [ "tokio-io-timeout", ] -[[package]] -name = "hyper-tls" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" -dependencies = [ - "bytes", - "hyper 0.14.29", - "native-tls", - "tokio", - "tokio-native-tls", -] - [[package]] name = "hyper-util" version = "0.1.5" @@ -2532,124 +2498,6 @@ dependencies = [ "cc", ] -[[package]] -name = "icu_collections" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db2fa452206ebee18c4b5c2274dbf1de17008e874b4dc4f0aea9d01ca79e4526" -dependencies = [ - "displaydoc", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_locid" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13acbb8371917fc971be86fc8057c41a64b521c184808a698c02acc242dbf637" -dependencies = [ - "displaydoc", - "litemap", - "tinystr", - "writeable", - "zerovec", -] - -[[package]] -name = "icu_locid_transform" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01d11ac35de8e40fdeda00d9e1e9d92525f3f9d887cdd7aa81d727596788b54e" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_locid_transform_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locid_transform_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" - -[[package]] -name = "icu_normalizer" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ce3e0da2ec68599d193c93d088142efd7f9c5d6fc9b803774855747dc6a84f" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_normalizer_data", - "icu_properties", - "icu_provider", - "smallvec", - "utf16_iter", - "utf8_iter", - "write16", - "zerovec", -] - -[[package]] -name = "icu_normalizer_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" - -[[package]] -name = "icu_properties" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f8ac670d7422d7f76b32e17a5db556510825b29ec9154f235977c9caba61036" -dependencies = [ - "displaydoc", - "icu_collections", - "icu_locid_transform", - "icu_properties_data", - "icu_provider", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_properties_data" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" - -[[package]] -name = "icu_provider" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ed421c8a8ef78d3e2dbc98a973be2f3770cb42b606e3ab18d6237c4dfde68d9" -dependencies = [ - "displaydoc", - "icu_locid", - "icu_provider_macros", - "stable_deref_trait", - "tinystr", - "writeable", - "yoke", - "zerofrom", - "zerovec", -] - -[[package]] -name = "icu_provider_macros" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ec89e9337638ecdc08744df490b221a7399bf8d164eb52a665454e60e075ad6" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "ident_case" version = "1.0.1" @@ -2676,18 +2524,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "idna" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4716a3a0933a1d01c2f72450e89596eb51dd34ef3c211ccd875acdf1f8fe47ed" -dependencies = [ - "icu_normalizer", - "icu_properties", - "smallvec", - "utf8_iter", -] - [[package]] name = "image" version = "0.24.9" @@ -2862,6 +2698,9 @@ name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +dependencies = [ + "spin 0.5.2", +] [[package]] name = "lazycell" @@ -3219,7 +3058,6 @@ dependencies = [ "lettre", "markdown-it", "once_cell", - "openssl", "pretty_assertions", "regex", "reqwest 0.11.27", @@ -3254,18 +3092,19 @@ dependencies = [ "fastrand", "futures-io", "futures-util", - "hostname", "httpdate", "idna 0.5.0", "mime", - "native-tls", "nom", "percent-encoding", "quoted_printable", + "rustls 0.23.10", + "rustls-pemfile 2.1.2", "socket2", "tokio", - "tokio-native-tls", + "tokio-rustls 0.26.0", "url", + "webpki-roots 0.26.2", ] [[package]] @@ -3281,9 +3120,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.5", ] +[[package]] +name = "libm" +version = "0.2.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" + [[package]] name = "line-wrap" version = "0.2.0" @@ -3311,12 +3156,6 @@ version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" -[[package]] -name = "litemap" -version = "0.7.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "643cb0b8d4fcc284004d5fd0d67ccf61dfffadb7f75e1e71bc420f4688a3a704" - [[package]] name = "local-channel" version = "0.1.5" @@ -3610,9 +3449,9 @@ checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] name = "moka" -version = "0.12.7" +version = "0.12.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e0d88686dc561d743b40de8269b26eaf0dc58781bde087b0984646602021d08" +checksum = "32cf62eb4dd975d2dde76432fb1075c49e3ee2331cf36f1f8fd4b66550d32b6f" dependencies = [ "async-lock", "async-trait", @@ -3644,23 +3483,6 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -[[package]] -name = "native-tls" -version = "0.2.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" -dependencies = [ - "libc", - "log", - "openssl", - "openssl-probe", - "openssl-sys", - "schannel", - "security-framework", - "security-framework-sys", - "tempfile", -] - [[package]] name = "never" version = "0.1.0" @@ -3703,6 +3525,23 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-bigint-dig" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc84195820f291c7697304f3cbdadd1cb7199c0efc917ff5eafd71225c136151" +dependencies = [ + "byteorder", + "lazy_static", + "libm", + "num-integer", + "num-iter", + "num-traits", + "rand", + "smallvec", + "zeroize", +] + [[package]] name = "num-conv" version = "0.1.0" @@ -3718,6 +3557,17 @@ dependencies = [ "num-traits", ] +[[package]] +name = "num-iter" +version = "0.1.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1429034a0490724d0075ebb2bc9e875d6503c3cf69e235a8941aa757d83ef5bf" +dependencies = [ + "autocfg", + "num-integer", + "num-traits", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -3725,6 +3575,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" dependencies = [ "autocfg", + "libm", ] [[package]] @@ -3752,50 +3603,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "openssl" -version = "0.10.64" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" -dependencies = [ - "bitflags 2.5.0", - "cfg-if", - "foreign-types", - "libc", - "once_cell", - "openssl-macros", - "openssl-sys", -] - -[[package]] -name = "openssl-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - -[[package]] -name = "openssl-probe" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" - -[[package]] -name = "openssl-sys" -version = "0.9.102" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" -dependencies = [ - "cc", - "libc", - "pkg-config", - "vcpkg", -] - [[package]] name = "opentelemetry" version = "0.16.0" @@ -4208,7 +4015,7 @@ dependencies = [ "tracing-subscriber", "url", "uuid", - "webpki-roots", + "webpki-roots 0.26.2", ] [[package]] @@ -4243,6 +4050,27 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" +[[package]] +name = "pkcs1" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8ffb9f10fa047879315e6625af03c164b16962a5368d724ed16323b68ace47f" +dependencies = [ + "der", + "pkcs8", + "spki", +] + +[[package]] +name = "pkcs8" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f950b2377845cebe5cf8b5165cb3cc1a5e0fa5cfa3e1f7f55707d8fd82e0a7b7" +dependencies = [ + "der", + "spki", +] + [[package]] name = "pkg-config" version = "0.3.30" @@ -4734,16 +4562,16 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.29", - "hyper-tls", + "hyper-rustls 0.24.2", "ipnet", "js-sys", "log", "mime", "mime_guess", - "native-tls", "once_cell", "percent-encoding", "pin-project-lite", + "rustls 0.21.12", "rustls-pemfile 1.0.4", "serde", "serde_json", @@ -4751,7 +4579,7 @@ dependencies = [ "sync_wrapper", "system-configuration", "tokio", - "tokio-native-tls", + "tokio-rustls 0.24.1", "tokio-util", "tower-service", "url", @@ -4759,6 +4587,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", + "webpki-roots 0.25.4", "winreg 0.50.0", ] @@ -4776,7 +4605,7 @@ dependencies = [ "http-body 1.0.0", "http-body-util", "hyper 1.3.1", - "hyper-rustls", + "hyper-rustls 0.26.0", "hyper-util", "ipnet", "js-sys", @@ -4801,7 +4630,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots", + "webpki-roots 0.26.2", "winreg 0.52.0", ] @@ -4894,7 +4723,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin", + "spin 0.9.8", "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -4931,6 +4760,26 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f8c01b9158de3aa5a7ac041a41c0e854d7adc3e473e7d7e2143eb5432bc5ba2" +[[package]] +name = "rsa" +version = "0.9.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0e5124fcb30e76a7e79bfee683a2746db83784b86289f6251b54b7950a0dfc" +dependencies = [ + "const-oid", + "digest", + "num-bigint-dig", + "num-integer", + "num-traits", + "pkcs1", + "pkcs8", + "rand_core", + "signature", + "spki", + "subtle", + "zeroize", +] + [[package]] name = "rss" version = "2.0.8" @@ -4977,6 +4826,18 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustls" +version = "0.21.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f56a14d1f48b391359b22f731fd4bd7e43c97f3c50eee276f3aa09c94784d3e" +dependencies = [ + "log", + "ring", + "rustls-webpki 0.101.7", + "sct", +] + [[package]] name = "rustls" version = "0.22.4" @@ -4986,7 +4847,7 @@ dependencies = [ "log", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.4", "subtle", "zeroize", ] @@ -5002,7 +4863,7 @@ dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki", + "rustls-webpki 0.102.4", "subtle", "zeroize", ] @@ -5042,6 +4903,16 @@ version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "976295e77ce332211c0d24d92c0e83e50f5c5f046d11082cea19f3df13a3562d" +[[package]] +name = "rustls-webpki" +version = "0.101.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b6275d1ee7a1cd780b64aca7726599a1dbc893b1e64144529e55c3c2f745765" +dependencies = [ + "ring", + "untrusted 0.9.0", +] + [[package]] name = "rustls-webpki" version = "0.102.4" @@ -5103,15 +4974,6 @@ dependencies = [ "sdd", ] -[[package]] -name = "schannel" -version = "0.1.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" -dependencies = [ - "windows-sys 0.52.0", -] - [[package]] name = "scoped-futures" version = "0.1.3" @@ -5128,35 +4990,22 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "sct" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" +dependencies = [ + "ring", + "untrusted 0.9.0", +] + [[package]] name = "sdd" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" -[[package]] -name = "security-framework" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" -dependencies = [ - "bitflags 2.5.0", - "core-foundation", - "core-foundation-sys", - "libc", - "security-framework-sys", -] - -[[package]] -name = "security-framework-sys" -version = "2.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "317936bbbd05227752583946b9e66d7ce3b489f84e11a94a510b4437fef407d7" -dependencies = [ - "core-foundation-sys", - "libc", -] - [[package]] name = "select" version = "0.6.0" @@ -5176,9 +5025,9 @@ checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" [[package]] name = "serde" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7253ab4de971e72fb7be983802300c30b5a7f0c2e56fab8abfc6a214307c0094" +checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12" dependencies = [ "serde_derive", ] @@ -5194,9 +5043,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.203" +version = "1.0.204" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "500cbc0ebeb6f46627f50f3f5811ccf6bf00643be300b4c3eabc0ef55dc5b5ba" +checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", @@ -5352,6 +5201,7 @@ version = "2.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77549399552de45a898a580c1b41d445bf730df867cc44e6c0233bbc4b8329de" dependencies = [ + "digest", "rand_core", ] @@ -5453,6 +5303,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + [[package]] name = "spin" version = "0.9.8" @@ -5469,12 +5325,6 @@ dependencies = [ "der", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - [[package]] name = "stacker" version = "0.1.15" @@ -5612,17 +5462,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" -[[package]] -name = "synstructure" -version = "0.13.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8af7666ab7b6390ab78131fb5b0fce11d6b7a6951602017c35fa82800708971" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "syntect" version = "5.2.0" @@ -5681,18 +5520,6 @@ dependencies = [ "pin-utils", ] -[[package]] -name = "tempfile" -version = "3.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" -dependencies = [ - "cfg-if", - "fastrand", - "rustix", - "windows-sys 0.52.0", -] - [[package]] name = "tendril" version = "0.4.3" @@ -5715,18 +5542,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c546c80d6be4bc6a00c0f01730c08df82eaa7a7a61f11d656526506112cc1709" +checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.61" +version = "1.0.62" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46c3384250002a6d5af4d114f2845d37b57521033f30d5c3f46c4d70e1197533" +checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" dependencies = [ "proc-macro2", "quote", @@ -5780,16 +5607,6 @@ version = "2.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ab95735ea2c8fd51154d01e39cf13912a78071c2d89abc49a7ef102a7dd725a" -[[package]] -name = "tinystr" -version = "0.7.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9117f5d4db391c1cf6927e7bea3db74b9a1c1add8f7eda9ffd5364f40f57b82f" -dependencies = [ - "displaydoc", - "zerovec", -] - [[package]] name = "tinyvec" version = "1.6.0" @@ -5867,16 +5684,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "tokio-native-tls" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" -dependencies = [ - "native-tls", - "tokio", -] - [[package]] name = "tokio-postgres" version = "0.7.10" @@ -5931,6 +5738,16 @@ dependencies = [ "x509-certificate", ] +[[package]] +name = "tokio-rustls" +version = "0.24.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c28327cf380ac148141087fbfb9de9d7bd4e84ab5d2c28fbc911d753de8a7081" +dependencies = [ + "rustls 0.21.12", + "tokio", +] + [[package]] name = "tokio-rustls" version = "0.25.0" @@ -6338,9 +6155,9 @@ dependencies = [ [[package]] name = "triomphe" -version = "0.1.12" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b2cb4fbb9995eeb36ac86fadf24031ccd58f99d6b4b2d7b911db70bddb80d90" +checksum = "859eb650cfee7434994602c3a68b25d77ad9e68c8a6cd491616ef86661382eb3" [[package]] name = "try-lock" @@ -6466,12 +6283,12 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.5.1" +version = "2.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7c25da092f0a868cdf09e8674cd3b7ef3a7d92a24253e663a2fb85e2496de56" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" dependencies = [ "form_urlencoded", - "idna 1.0.0", + "idna 0.5.0", "percent-encoding", "serde", ] @@ -6488,24 +6305,12 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" -[[package]] -name = "utf16_iter" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8232dd3cdaed5356e0f716d285e4b40b932ac434100fe9b7e0e8e935b9e6246" - [[package]] name = "utf8-width" version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" -[[package]] -name = "utf8_iter" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" - [[package]] name = "utf8parse" version = "0.2.1" @@ -6674,8 +6479,7 @@ dependencies = [ [[package]] name = "webmention" version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d07b90492f7b6fe35f5298fcd01c663d3c453e8c302dc86c7292c6681b8117d" +source = "git+https://github.com/dessalines/webmention?branch=remove_reqwest_default_features#f40ac54ebba08baf041ea54ed1c61191cd60c7a4" dependencies = [ "anyhow", "nom", @@ -6699,6 +6503,12 @@ dependencies = [ "url", ] +[[package]] +name = "webpki-roots" +version = "0.25.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" + [[package]] name = "webpki-roots" version = "0.26.2" @@ -6762,16 +6572,6 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" -[[package]] -name = "windows" -version = "0.52.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" -dependencies = [ - "windows-core", - "windows-targets 0.52.5", -] - [[package]] name = "windows-core" version = "0.52.0" @@ -6958,18 +6758,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "write16" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1890f4022759daae28ed4fe62859b1236caebfc61ede2f63ed4e695f3f6d936" - -[[package]] -name = "writeable" -version = "0.5.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e9df38ee2d2c3c5948ea468a8406ff0db0b29ae1ffde1bcf20ef305bcc95c51" - [[package]] name = "x509-cert" version = "0.2.5" @@ -7044,30 +6832,6 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" -[[package]] -name = "yoke" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c5b1314b079b0930c31e3af543d8ee1757b1951ae1e1565ec704403a7240ca5" -dependencies = [ - "serde", - "stable_deref_trait", - "yoke-derive", - "zerofrom", -] - -[[package]] -name = "yoke-derive" -version = "0.7.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cc31741b18cb6f1d5ff12f5b7523e3d6eb0852bbbad19d73905511d9849b95" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zerocopy" version = "0.7.34" @@ -7088,27 +6852,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerofrom" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91ec111ce797d0e0784a1116d0ddcdbea84322cd79e5d5ad173daeba4f93ab55" -dependencies = [ - "zerofrom-derive", -] - -[[package]] -name = "zerofrom-derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ea7b4a3637ea8669cedf0f1fd5c286a17f3de97b8dd5a70a6c167a1730e63a5" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", - "synstructure", -] - [[package]] name = "zeroize" version = "1.8.1" @@ -7129,28 +6872,6 @@ dependencies = [ "syn 2.0.66", ] -[[package]] -name = "zerovec" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb2cc8827d6c0994478a15c53f374f46fbd41bea663d809b14744bc42e6b109c" -dependencies = [ - "yoke", - "zerofrom", - "zerovec-derive", -] - -[[package]] -name = "zerovec-derive" -version = "0.10.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97cf56601ee5052b4417d90c8755c6683473c926039908196cf35d99f893ebe7" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.66", -] - [[package]] name = "zstd" version = "0.13.1" diff --git a/Cargo.toml b/Cargo.toml index ce6d3357d..461a6cc84 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -99,7 +99,7 @@ lemmy_db_views = { version = "=0.19.5", path = "./crates/db_views" } lemmy_db_views_actor = { version = "=0.19.5", path = "./crates/db_views_actor" } lemmy_db_views_moderator = { version = "=0.19.5", path = "./crates/db_views_moderator" } lemmy_federate = { version = "=0.19.5", path = "./crates/federate" } -activitypub_federation = { version = "0.5.6", default-features = false, features = [ +activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diesel = "2.1.6" @@ -121,7 +121,12 @@ tracing-error = "0.2.0" tracing-log = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } url = { version = "2.5.0", features = ["serde"] } -reqwest = { version = "0.11.27", features = ["json", "blocking", "gzip"] } +reqwest = { version = "0.11.27", default-features = false, features = [ + "json", + "blocking", + "gzip", + "rustls-tls", +] } reqwest-middleware = "0.2.5" reqwest-tracing = "0.4.8" clokwerk = "0.4.0" diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index af50c5648..32d2457bd 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -28,7 +28,7 @@ uuid = { workspace = true } moka.workspace = true once_cell.workspace = true anyhow.workspace = true -webmention = "0.5.0" +webmention = { git = "https://github.com/dessalines/webmention", branch = "remove_reqwest_default_features" } accept-language = "3.1.0" [package.metadata.cargo-machete] diff --git a/crates/db_schema/src/impls/local_user_vote_display_mode.rs b/crates/db_schema/src/impls/local_user_vote_display_mode.rs index d77502335..2d169f81b 100644 --- a/crates/db_schema/src/impls/local_user_vote_display_mode.rs +++ b/crates/db_schema/src/impls/local_user_vote_display_mode.rs @@ -31,6 +31,7 @@ impl LocalUserVoteDisplayMode { .get_result::(conn) .await } + pub async fn update( pool: &mut DbPool<'_>, local_user_id: LocalUserId, diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 046c0a872..b9cf9ae21 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -44,7 +44,6 @@ full = [ "dep:enum-map", "dep:futures", "dep:tokio", - "dep:openssl", "dep:html2text", "dep:lettre", "dep:uuid", @@ -74,13 +73,14 @@ uuid = { workspace = true, features = ["serde", "v4"], optional = true } rosetta-i18n = { workspace = true, optional = true } tokio = { workspace = true, optional = true } urlencoding = { workspace = true, optional = true } -openssl = { version = "0.10.64", optional = true } html2text = { version = "0.12.5", optional = true } deser-hjson = { version = "2.2.4", optional = true } smart-default = { version = "0.7.1", optional = true } -lettre = { version = "0.11.7", features = [ +lettre = { version = "0.11.7", default-features = false, features = [ + "builder", "tokio1", - "tokio1-native-tls", + "tokio1-rustls-tls", + "smtp-transport", ], optional = true } markdown-it = { version = "0.6.0", optional = true } ts-rs = { workspace = true, optional = true } diff --git a/crates/utils/src/apub.rs b/crates/utils/src/apub.rs deleted file mode 100644 index 53e069d77..000000000 --- a/crates/utils/src/apub.rs +++ /dev/null @@ -1,26 +0,0 @@ -use openssl::{pkey::PKey, rsa::Rsa}; -use std::io::{Error, ErrorKind}; - -pub struct Keypair { - pub private_key: String, - pub public_key: String, -} - -/// Generate the asymmetric keypair for ActivityPub HTTP signatures. -pub fn generate_actor_keypair() -> Result { - let rsa = Rsa::generate(2048)?; - let pkey = PKey::from_rsa(rsa)?; - let public_key = pkey.public_key_to_pem()?; - let private_key = pkey.private_key_to_pem_pkcs8()?; - let key_to_string = |key| match String::from_utf8(key) { - Ok(s) => Ok(s), - Err(e) => Err(Error::new( - ErrorKind::Other, - format!("Failed converting key to string: {e}"), - )), - }; - Ok(Keypair { - private_key: key_to_string(private_key)?, - public_key: key_to_string(public_key)?, - }) -} diff --git a/crates/utils/src/lib.rs b/crates/utils/src/lib.rs index 1adb3f6cf..5a5e76d2a 100644 --- a/crates/utils/src/lib.rs +++ b/crates/utils/src/lib.rs @@ -2,7 +2,6 @@ use cfg_if::cfg_if; cfg_if! { if #[cfg(feature = "full")] { - pub mod apub; pub mod cache_header; pub mod email; pub mod rate_limit; From 073ff446767970d73763804d3be390695beeffd4 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Fri, 19 Jul 2024 04:18:45 -0400 Subject: [PATCH 19/69] Reverting webmention git dep to not break publish. (#4904) - Context: #4901 --- Cargo.lock | 149 ++++++++++++++++++++++++++++++++++++- crates/api_crud/Cargo.toml | 2 +- 2 files changed, 149 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 728eb21ba..b15baa903 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1891,6 +1891,21 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "foreign-types" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" +dependencies = [ + "foreign-types-shared", +] + +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -2435,6 +2450,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-tls" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" +dependencies = [ + "bytes", + "hyper 0.14.29", + "native-tls", + "tokio", + "tokio-native-tls", +] + [[package]] name = "hyper-util" version = "0.1.5" @@ -3483,6 +3511,23 @@ version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" +[[package]] +name = "native-tls" +version = "0.2.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8614eb2c83d59d1c8cc974dd3f920198647674a0a035e1af1fa58707e317466" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + [[package]] name = "never" version = "0.1.0" @@ -3603,6 +3648,50 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" +[[package]] +name = "openssl" +version = "0.10.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +dependencies = [ + "bitflags 2.5.0", + "cfg-if", + "foreign-types", + "libc", + "once_cell", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + +[[package]] +name = "openssl-probe" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" + +[[package]] +name = "openssl-sys" +version = "0.9.102" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +dependencies = [ + "cc", + "libc", + "pkg-config", + "vcpkg", +] + [[package]] name = "opentelemetry" version = "0.16.0" @@ -4563,11 +4652,13 @@ dependencies = [ "http-body 0.4.6", "hyper 0.14.29", "hyper-rustls 0.24.2", + "hyper-tls", "ipnet", "js-sys", "log", "mime", "mime_guess", + "native-tls", "once_cell", "percent-encoding", "pin-project-lite", @@ -4579,6 +4670,7 @@ dependencies = [ "sync_wrapper", "system-configuration", "tokio", + "tokio-native-tls", "tokio-rustls 0.24.1", "tokio-util", "tower-service", @@ -4974,6 +5066,15 @@ dependencies = [ "sdd", ] +[[package]] +name = "schannel" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbc91545643bcf3a0bbb6569265615222618bdf33ce4ffbbd13c4bbd4c093534" +dependencies = [ + "windows-sys 0.52.0", +] + [[package]] name = "scoped-futures" version = "0.1.3" @@ -5006,6 +5107,29 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +[[package]] +name = "security-framework" +version = "2.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +dependencies = [ + "bitflags 2.5.0", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75da29fe9b9b08fe9d6b22b5b4bcbc75d8db3aa31e639aa56bb62e9d46bfceaf" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "select" version = "0.6.0" @@ -5520,6 +5644,18 @@ dependencies = [ "pin-utils", ] +[[package]] +name = "tempfile" +version = "3.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" +dependencies = [ + "cfg-if", + "fastrand", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "tendril" version = "0.4.3" @@ -5684,6 +5820,16 @@ dependencies = [ "syn 2.0.66", ] +[[package]] +name = "tokio-native-tls" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbae76ab933c85776efabc971569dd6119c580d8f5d448769dec1764bf796ef2" +dependencies = [ + "native-tls", + "tokio", +] + [[package]] name = "tokio-postgres" version = "0.7.10" @@ -6479,7 +6625,8 @@ dependencies = [ [[package]] name = "webmention" version = "0.5.0" -source = "git+https://github.com/dessalines/webmention?branch=remove_reqwest_default_features#f40ac54ebba08baf041ea54ed1c61191cd60c7a4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d07b90492f7b6fe35f5298fcd01c663d3c453e8c302dc86c7292c6681b8117d" dependencies = [ "anyhow", "nom", diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index 32d2457bd..af50c5648 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -28,7 +28,7 @@ uuid = { workspace = true } moka.workspace = true once_cell.workspace = true anyhow.workspace = true -webmention = { git = "https://github.com/dessalines/webmention", branch = "remove_reqwest_default_features" } +webmention = "0.5.0" accept-language = "3.1.0" [package.metadata.cargo-machete] From a08642f81377e8ef01f91f5d49f531e71fd62d70 Mon Sep 17 00:00:00 2001 From: phiresky Date: Sun, 21 Jul 2024 17:50:50 +0200 Subject: [PATCH 20/69] federation: parallel sending per instance (#4623) * federation: parallel sending * federation: some comments * lint and set force_write true when a request fails * inbox_urls return vec * split inbox functions into separate file * cleanup * extract sending task code to separate file * move federation concurrent config to config file * off by one issue * improve msg * fix both permanent stopping of federation queues and multiple creation of the same federation queues * fix after merge * lint fix * Update crates/federate/src/send.rs Co-authored-by: dullbananas * comment about reverse ordering * remove crashable, comment * comment * move comment * run federation tests twice * fix test run * prettier * fix config default * upgrade rust to 1.78 to fix diesel cli * fix clippy * delay * add debug to make localhost urls not valid in ap crate, add some debug logs * federation tests: ensure server stop after test and random activity id * ci fix * add test to federate 100 events * fix send 100 test * different data every time so activities are distinguishable * allow out of order receives in test * lint * comment about https://github.com/LemmyNet/lemmy/pull/4623#discussion_r1565437391 * move sender for clarity, add comment * move more things to members * update test todo comment, use same env var as worker test but default to 1 * remove else below continue * some more cleanup * handle todo about smooth exit * add federate inboxes collector tests * lint * actor max length * don't reset fail count if activity skipped * fix some comments * reuse vars * format * Update .woodpecker.yml * fix recheck time * fix inboxes tests under fast mode * format * make i32 and ugly casts * clippy --------- Co-authored-by: dullbananas --- .woodpecker.yml | 1 + Cargo.lock | 120 ++++ api_tests/src/follow.spec.ts | 67 +- api_tests/src/post.spec.ts | 30 +- api_tests/src/user.spec.ts | 6 +- config/defaults.hjson | 10 +- crates/api_common/src/context.rs | 11 +- crates/db_schema/src/newtypes.rs | 2 +- crates/federate/Cargo.toml | 7 + crates/federate/src/inboxes.rs | 572 ++++++++++++++++ crates/federate/src/lib.rs | 56 +- crates/federate/src/send.rs | 148 +++++ crates/federate/src/util.rs | 33 +- crates/federate/src/worker.rs | 932 +++++++++++++++++++-------- crates/utils/src/settings/structs.rs | 19 +- scripts/test.sh | 1 + src/lib.rs | 1 + 17 files changed, 1686 insertions(+), 330 deletions(-) create mode 100644 crates/federate/src/inboxes.rs create mode 100644 crates/federate/src/send.rs diff --git a/.woodpecker.yml b/.woodpecker.yml index fe11411d8..d12f12326 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -181,6 +181,7 @@ steps: LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy RUST_BACKTRACE: "1" CARGO_HOME: .cargo_home + LEMMY_TEST_FAST_FEDERATION: "1" commands: - export LEMMY_CONFIG_LOCATION=../../config/config.hjson - cargo test --workspace --no-fail-fast diff --git a/Cargo.lock b/Cargo.lock index b15baa903..e1b90a9f0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1674,6 +1674,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "downcast" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1" + [[package]] name = "downcast-rs" version = "1.2.1" @@ -1915,6 +1921,12 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fragile" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa" + [[package]] name = "fs2" version = "0.4.3" @@ -2980,7 +2992,9 @@ name = "lemmy_federate" version = "0.19.5" dependencies = [ "activitypub_federation", + "actix-web", "anyhow", + "async-trait", "chrono", "diesel", "diesel-async", @@ -2990,14 +3004,19 @@ dependencies = [ "lemmy_db_schema", "lemmy_db_views_actor", "lemmy_utils", + "mockall", "moka", "once_cell", "reqwest 0.11.27", "serde_json", "serial_test", + "test-context", "tokio", "tokio-util", "tracing", + "tracing-test", + "url", + "uuid", ] [[package]] @@ -3475,6 +3494,33 @@ version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" +[[package]] +name = "mockall" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +dependencies = [ + "cfg-if", + "downcast", + "fragile", + "lazy_static", + "mockall_derive", + "predicates", + "predicates-tree", +] + +[[package]] +name = "mockall_derive" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +dependencies = [ + "cfg-if", + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "moka" version = "0.12.8" @@ -4273,6 +4319,32 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" +[[package]] +name = "predicates" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +dependencies = [ + "anstyle", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" + +[[package]] +name = "predicates-tree" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +dependencies = [ + "predicates-core", + "termtree", +] + [[package]] name = "pretty_assertions" version = "1.4.0" @@ -5676,6 +5748,33 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "termtree" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76" + +[[package]] +name = "test-context" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6676ab8513edfd2601a108621103fdb45cac9098305ca25ec93f7023b06b05d9" +dependencies = [ + "futures", + "test-context-macros", +] + +[[package]] +name = "test-context-macros" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ea17a2dc368aeca6f554343ced1b1e31f76d63683fa8016e5844bd7a5144a1" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.66", +] + [[package]] name = "thiserror" version = "1.0.62" @@ -6299,6 +6398,27 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "tracing-test" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "557b891436fe0d5e0e363427fc7f217abf9ccd510d5136549847bdcbcd011d68" +dependencies = [ + "tracing-core", + "tracing-subscriber", + "tracing-test-macro", +] + +[[package]] +name = "tracing-test-macro" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" +dependencies = [ + "quote", + "syn 2.0.66", +] + [[package]] name = "triomphe" version = "0.1.11" diff --git a/api_tests/src/follow.spec.ts b/api_tests/src/follow.spec.ts index 161c7f045..22fdfa305 100644 --- a/api_tests/src/follow.spec.ts +++ b/api_tests/src/follow.spec.ts @@ -11,6 +11,7 @@ import { betaUrl, registerUser, unfollows, + delay, } from "./shared"; beforeAll(setupLogins); @@ -21,39 +22,48 @@ test("Follow local community", async () => { let user = await registerUser(beta, betaUrl); let community = (await resolveBetaCommunity(user)).community!; - expect(community.counts.subscribers).toBe(1); - expect(community.counts.subscribers_local).toBe(1); let follow = await followCommunity(user, true, community.community.id); // Make sure the follow response went through expect(follow.community_view.community.local).toBe(true); expect(follow.community_view.subscribed).toBe("Subscribed"); - expect(follow.community_view.counts.subscribers).toBe(2); - expect(follow.community_view.counts.subscribers_local).toBe(2); + expect(follow.community_view.counts.subscribers).toBe( + community.counts.subscribers + 1, + ); + expect(follow.community_view.counts.subscribers_local).toBe( + community.counts.subscribers_local + 1, + ); // Test an unfollow let unfollow = await followCommunity(user, false, community.community.id); expect(unfollow.community_view.subscribed).toBe("NotSubscribed"); - expect(unfollow.community_view.counts.subscribers).toBe(1); - expect(unfollow.community_view.counts.subscribers_local).toBe(1); + expect(unfollow.community_view.counts.subscribers).toBe( + community.counts.subscribers, + ); + expect(unfollow.community_view.counts.subscribers_local).toBe( + community.counts.subscribers_local, + ); }); test("Follow federated community", async () => { // It takes about 1 second for the community aggregates to federate - let betaCommunity = ( + await delay(2000); // if this is the second test run, we don't have a way to wait for the correct number of subscribers + const betaCommunityInitial = ( await waitUntil( () => resolveBetaCommunity(alpha), - c => - c.community?.counts.subscribers === 1 && - c.community.counts.subscribers_local === 0, + c => !!c.community && c.community?.counts.subscribers >= 1, ) ).community; - if (!betaCommunity) { + if (!betaCommunityInitial) { throw "Missing beta community"; } - let follow = await followCommunity(alpha, true, betaCommunity.community.id); + let follow = await followCommunity( + alpha, + true, + betaCommunityInitial.community.id, + ); expect(follow.community_view.subscribed).toBe("Pending"); - betaCommunity = ( + const betaCommunity = ( await waitUntil( () => resolveBetaCommunity(alpha), c => c.community?.subscribed === "Subscribed", @@ -64,20 +74,24 @@ test("Follow federated community", async () => { expect(betaCommunity?.community.local).toBe(false); expect(betaCommunity?.community.name).toBe("main"); expect(betaCommunity?.subscribed).toBe("Subscribed"); - expect(betaCommunity?.counts.subscribers_local).toBe(1); + expect(betaCommunity?.counts.subscribers_local).toBe( + betaCommunityInitial.counts.subscribers_local + 1, + ); // check that unfollow was federated let communityOnBeta1 = await resolveBetaCommunity(beta); - expect(communityOnBeta1.community?.counts.subscribers).toBe(2); - expect(communityOnBeta1.community?.counts.subscribers_local).toBe(1); + expect(communityOnBeta1.community?.counts.subscribers).toBe( + betaCommunityInitial.counts.subscribers + 1, + ); // Check it from local let site = await getSite(alpha); let remoteCommunityId = site.my_user?.follows.find( - c => c.community.local == false, + c => + c.community.local == false && + c.community.id === betaCommunityInitial.community.id, )?.community.id; expect(remoteCommunityId).toBeDefined(); - expect(site.my_user?.follows.length).toBe(2); if (!remoteCommunityId) { throw "Missing remote community id"; @@ -89,10 +103,21 @@ test("Follow federated community", async () => { // Make sure you are unsubbed locally let siteUnfollowCheck = await getSite(alpha); - expect(siteUnfollowCheck.my_user?.follows.length).toBe(1); + expect( + siteUnfollowCheck.my_user?.follows.find( + c => c.community.id === betaCommunityInitial.community.id, + ), + ).toBe(undefined); // check that unfollow was federated - let communityOnBeta2 = await resolveBetaCommunity(beta); - expect(communityOnBeta2.community?.counts.subscribers).toBe(1); + let communityOnBeta2 = await waitUntil( + () => resolveBetaCommunity(beta), + c => + c.community?.counts.subscribers === + betaCommunityInitial.counts.subscribers, + ); + expect(communityOnBeta2.community?.counts.subscribers).toBe( + betaCommunityInitial.counts.subscribers, + ); expect(communityOnBeta2.community?.counts.subscribers_local).toBe(1); }); diff --git a/api_tests/src/post.spec.ts b/api_tests/src/post.spec.ts index fe17bd979..6b5c8d812 100644 --- a/api_tests/src/post.spec.ts +++ b/api_tests/src/post.spec.ts @@ -52,17 +52,23 @@ beforeAll(async () => { afterAll(unfollows); -async function assertPostFederation(postOne: PostView, postTwo: PostView) { +async function assertPostFederation( + postOne: PostView, + postTwo: PostView, + waitForMeta = true, +) { // Link metadata is generated in background task and may not be ready yet at this time, // so wait for it explicitly. For removed posts we cant refetch anything. - postOne = await waitForPost(beta, postOne.post, res => { - return res === null || res?.post.embed_title !== null; - }); - postTwo = await waitForPost( - beta, - postTwo.post, - res => res === null || res?.post.embed_title !== null, - ); + if (waitForMeta) { + postOne = await waitForPost(beta, postOne.post, res => { + return res === null || !!res?.post.embed_title; + }); + postTwo = await waitForPost( + beta, + postTwo.post, + res => res === null || !!res?.post.embed_title, + ); + } expect(postOne?.post.ap_id).toBe(postTwo?.post.ap_id); expect(postOne?.post.name).toBe(postTwo?.post.name); @@ -408,7 +414,11 @@ test("Remove a post from admin and community on same instance", async () => { p => p?.post_view.post.removed ?? false, ); expect(alphaPost?.post_view.post.removed).toBe(true); - await assertPostFederation(alphaPost.post_view, removePostRes.post_view); + await assertPostFederation( + alphaPost.post_view, + removePostRes.post_view, + false, + ); // Undelete let undeletedPost = await removePost(beta, false, betaPost.post); diff --git a/api_tests/src/user.spec.ts b/api_tests/src/user.spec.ts index d008dcdc3..2edcf54ea 100644 --- a/api_tests/src/user.spec.ts +++ b/api_tests/src/user.spec.ts @@ -131,7 +131,11 @@ test("Requests with invalid auth should be treated as unauthenticated", async () }); test("Create user with Arabic name", async () => { - let user = await registerUser(alpha, alphaUrl, "تجريب"); + let user = await registerUser( + alpha, + alphaUrl, + "تجريب" + Math.random().toString().slice(2, 10), // less than actor_name_max_length + ); let site = await getSite(user); expect(site.my_user).toBeDefined(); diff --git a/config/defaults.hjson b/config/defaults.hjson index e8a70ebae..4bce48b5f 100644 --- a/config/defaults.hjson +++ b/config/defaults.hjson @@ -108,10 +108,12 @@ port: 8536 # Whether the site is available over TLS. Needs to be true for federation to work. tls_enabled: true - # The number of activitypub federation workers that can be in-flight concurrently - worker_count: 0 - # The number of activitypub federation retry workers that can be in-flight concurrently - retry_count: 0 + federation: { + # Limit to the number of concurrent outgoing federation requests per target instance. + # Set this to a higher value than 1 (e.g. 6) only if you have a huge instance (>10 activities + # per second) and if a receiving instance is not keeping up. + concurrent_sends_per_instance: 1 + } prometheus: { bind: "127.0.0.1" port: 10002 diff --git a/crates/api_common/src/context.rs b/crates/api_common/src/context.rs index f4ac41db1..334983b20 100644 --- a/crates/api_common/src/context.rs +++ b/crates/api_common/src/context.rs @@ -55,7 +55,7 @@ impl LemmyContext { /// Initialize a context for use in tests which blocks federation network calls. /// /// Do not use this in production code. - pub async fn init_test_context() -> Data { + pub async fn init_test_federation_config() -> FederationConfig { // call this to run migrations let pool = build_db_pool_for_tests().await; @@ -70,14 +70,19 @@ impl LemmyContext { let rate_limit_cell = RateLimitCell::with_test_config(); let context = LemmyContext::create(pool, client, secret, rate_limit_cell.clone()); - let config = FederationConfig::builder() + + FederationConfig::builder() .domain(context.settings().hostname.clone()) .app_data(context) + .debug(true) // Dont allow any network fetches .http_fetch_limit(0) .build() .await - .expect("build federation config"); + .expect("build federation config") + } + pub async fn init_test_context() -> Data { + let config = Self::init_test_federation_config().await; config.to_request_data() } } diff --git a/crates/db_schema/src/newtypes.rs b/crates/db_schema/src/newtypes.rs index c5c9e8e84..9aeaa5266 100644 --- a/crates/db_schema/src/newtypes.rs +++ b/crates/db_schema/src/newtypes.rs @@ -107,7 +107,7 @@ pub struct PrivateMessageReportId(i32); #[cfg_attr(feature = "full", derive(DieselNewType, TS))] #[cfg_attr(feature = "full", ts(export))] /// The site id. -pub struct SiteId(i32); +pub struct SiteId(pub i32); #[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] #[cfg_attr(feature = "full", derive(DieselNewType, TS))] diff --git a/crates/federate/Cargo.toml b/crates/federate/Cargo.toml index 2405d3af0..b8b438901 100644 --- a/crates/federate/Cargo.toml +++ b/crates/federate/Cargo.toml @@ -34,6 +34,13 @@ tokio = { workspace = true, features = ["full"] } tracing.workspace = true moka.workspace = true tokio-util = "0.7.11" +async-trait.workspace = true [dev-dependencies] serial_test = { workspace = true } +url.workspace = true +actix-web.workspace = true +tracing-test = "0.2.5" +uuid.workspace = true +test-context = "0.3.0" +mockall = "0.12.1" diff --git a/crates/federate/src/inboxes.rs b/crates/federate/src/inboxes.rs new file mode 100644 index 000000000..9869e5270 --- /dev/null +++ b/crates/federate/src/inboxes.rs @@ -0,0 +1,572 @@ +use crate::util::LEMMY_TEST_FAST_FEDERATION; +use anyhow::Result; +use async_trait::async_trait; +use chrono::{DateTime, TimeZone, Utc}; +use lemmy_db_schema::{ + newtypes::{CommunityId, DbUrl, InstanceId}, + source::{activity::SentActivity, site::Site}, + utils::{ActualDbPool, DbPool}, +}; +use lemmy_db_views_actor::structs::CommunityFollowerView; +use once_cell::sync::Lazy; +use reqwest::Url; +use std::collections::{HashMap, HashSet}; + +/// interval with which new additions to community_followers are queried. +/// +/// The first time some user on an instance follows a specific remote community (or, more precisely: +/// the first time a (followed_community_id, follower_inbox_url) tuple appears), this delay limits +/// the maximum time until the follow actually results in activities from that community id being +/// sent to that inbox url. This delay currently needs to not be too small because the DB load is +/// currently fairly high because of the current structure of storing inboxes for every person, not +/// having a separate list of shared_inboxes, and the architecture of having every instance queue be +/// fully separate. (see https://github.com/LemmyNet/lemmy/issues/3958) +static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = Lazy::new(|| { + if *LEMMY_TEST_FAST_FEDERATION { + chrono::TimeDelta::try_seconds(1).expect("TimeDelta out of bounds") + } else { + chrono::TimeDelta::try_minutes(2).expect("TimeDelta out of bounds") + } +}); +/// The same as FOLLOW_ADDITIONS_RECHECK_DELAY, but triggering when the last person on an instance +/// unfollows a specific remote community. This is expected to happen pretty rarely and updating it +/// in a timely manner is not too important. +static FOLLOW_REMOVALS_RECHECK_DELAY: Lazy = + Lazy::new(|| chrono::TimeDelta::try_hours(1).expect("TimeDelta out of bounds")); + +#[async_trait] +pub trait DataSource: Send + Sync { + async fn read_site_from_instance_id( + &self, + instance_id: InstanceId, + ) -> Result, diesel::result::Error>; + async fn get_instance_followed_community_inboxes( + &self, + instance_id: InstanceId, + last_fetch: DateTime, + ) -> Result, diesel::result::Error>; +} +pub struct DbDataSource { + pool: ActualDbPool, +} + +impl DbDataSource { + pub fn new(pool: ActualDbPool) -> Self { + Self { pool } + } +} + +#[async_trait] +impl DataSource for DbDataSource { + async fn read_site_from_instance_id( + &self, + instance_id: InstanceId, + ) -> Result, diesel::result::Error> { + Site::read_from_instance_id(&mut DbPool::Pool(&self.pool), instance_id).await + } + + async fn get_instance_followed_community_inboxes( + &self, + instance_id: InstanceId, + last_fetch: DateTime, + ) -> Result, diesel::result::Error> { + CommunityFollowerView::get_instance_followed_community_inboxes( + &mut DbPool::Pool(&self.pool), + instance_id, + last_fetch, + ) + .await + } +} + +pub(crate) struct CommunityInboxCollector { + // load site lazily because if an instance is first seen due to being on allowlist, + // the corresponding row in `site` may not exist yet since that is only added once + // `fetch_instance_actor_for_object` is called. + // (this should be unlikely to be relevant outside of the federation tests) + site_loaded: bool, + site: Option, + followed_communities: HashMap>, + last_full_communities_fetch: DateTime, + last_incremental_communities_fetch: DateTime, + instance_id: InstanceId, + domain: String, + pub(crate) data_source: T, +} + +pub type RealCommunityInboxCollector = CommunityInboxCollector; + +impl CommunityInboxCollector { + pub fn new_real( + pool: ActualDbPool, + instance_id: InstanceId, + domain: String, + ) -> RealCommunityInboxCollector { + CommunityInboxCollector::new(DbDataSource::new(pool), instance_id, domain) + } + pub fn new( + data_source: T, + instance_id: InstanceId, + domain: String, + ) -> CommunityInboxCollector { + CommunityInboxCollector { + data_source, + site_loaded: false, + site: None, + followed_communities: HashMap::new(), + last_full_communities_fetch: Utc.timestamp_nanos(0), + last_incremental_communities_fetch: Utc.timestamp_nanos(0), + instance_id, + domain, + } + } + /// get inbox urls of sending the given activity to the given instance + /// most often this will return 0 values (if instance doesn't care about the activity) + /// or 1 value (the shared inbox) + /// > 1 values only happens for non-lemmy software + pub async fn get_inbox_urls(&mut self, activity: &SentActivity) -> Result> { + let mut inbox_urls: HashSet = HashSet::new(); + + if activity.send_all_instances { + if !self.site_loaded { + self.site = self + .data_source + .read_site_from_instance_id(self.instance_id) + .await?; + self.site_loaded = true; + } + if let Some(site) = &self.site { + // Nutomic: Most non-lemmy software wont have a site row. That means it cant handle these + // activities. So handling it like this is fine. + inbox_urls.insert(site.inbox_url.inner().clone()); + } + } + if let Some(t) = &activity.send_community_followers_of { + if let Some(urls) = self.followed_communities.get(t) { + inbox_urls.extend(urls.iter().cloned()); + } + } + inbox_urls.extend( + activity + .send_inboxes + .iter() + .filter_map(std::option::Option::as_ref) + // a similar filter also happens within the activitypub-federation crate. but that filter + // happens much later - by doing it here, we can ensure that in the happy case, this + // function returns 0 urls which means the system doesn't have to create a tokio + // task for sending at all (since that task has a fair amount of overhead) + .filter(|&u| (u.domain() == Some(&self.domain))) + .map(|u| u.inner().clone()), + ); + tracing::trace!( + "get_inbox_urls: {:?}, send_inboxes: {:?}", + inbox_urls, + activity.send_inboxes + ); + Ok(inbox_urls.into_iter().collect()) + } + + pub async fn update_communities(&mut self) -> Result<()> { + if (Utc::now() - self.last_full_communities_fetch) > *FOLLOW_REMOVALS_RECHECK_DELAY { + tracing::debug!("{}: fetching full list of communities", self.domain); + // process removals every hour + (self.followed_communities, self.last_full_communities_fetch) = self + .get_communities(self.instance_id, Utc.timestamp_nanos(0)) + .await?; + self.last_incremental_communities_fetch = self.last_full_communities_fetch; + } + if (Utc::now() - self.last_incremental_communities_fetch) > *FOLLOW_ADDITIONS_RECHECK_DELAY { + // process additions every minute + let (news, time) = self + .get_communities(self.instance_id, self.last_incremental_communities_fetch) + .await?; + if !news.is_empty() { + tracing::debug!( + "{}: fetched {} incremental new followed communities", + self.domain, + news.len() + ); + } + self.followed_communities.extend(news); + self.last_incremental_communities_fetch = time; + } + Ok(()) + } + + /// get a list of local communities with the remote inboxes on the given instance that cares about + /// them + async fn get_communities( + &mut self, + instance_id: InstanceId, + last_fetch: DateTime, + ) -> Result<(HashMap>, DateTime)> { + // update to time before fetch to ensure overlap. subtract some time to ensure overlap even if + // published date is not exact + let new_last_fetch = Utc::now() - *FOLLOW_ADDITIONS_RECHECK_DELAY / 2; + + let inboxes = self + .data_source + .get_instance_followed_community_inboxes(instance_id, last_fetch) + .await?; + + let map: HashMap> = + inboxes.into_iter().fold(HashMap::new(), |mut map, (c, u)| { + map.entry(c).or_default().insert(u.into()); + map + }); + + Ok((map, new_last_fetch)) + } +} + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +#[allow(clippy::indexing_slicing)] +mod tests { + use super::*; + use lemmy_db_schema::{ + newtypes::{ActivityId, CommunityId, InstanceId, SiteId}, + source::activity::{ActorType, SentActivity}, + }; + use mockall::{mock, predicate::*}; + use serde_json::json; + mock! { + DataSource {} + #[async_trait] + impl DataSource for DataSource { + async fn read_site_from_instance_id(&self, instance_id: InstanceId) -> Result, diesel::result::Error>; + async fn get_instance_followed_community_inboxes( + &self, + instance_id: InstanceId, + last_fetch: DateTime, + ) -> Result, diesel::result::Error>; + } + } + + fn setup_collector() -> CommunityInboxCollector { + let mock_data_source = MockDataSource::new(); + let instance_id = InstanceId(1); + let domain = "example.com".to_string(); + CommunityInboxCollector::new(mock_data_source, instance_id, domain) + } + + #[tokio::test] + async fn test_get_inbox_urls_empty() { + let mut collector = setup_collector(); + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![], + send_community_followers_of: None, + send_all_instances: false, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert!(result.is_empty()); + } + + #[tokio::test] + async fn test_get_inbox_urls_send_all_instances() { + let mut collector = setup_collector(); + let site_inbox = Url::parse("https://example.com/inbox").unwrap(); + let site = Site { + id: SiteId(1), + name: "Test Site".to_string(), + sidebar: None, + published: Utc::now(), + updated: None, + icon: None, + banner: None, + description: None, + actor_id: Url::parse("https://example.com/site").unwrap().into(), + last_refreshed_at: Utc::now(), + inbox_url: site_inbox.clone().into(), + private_key: None, + public_key: "test_key".to_string(), + instance_id: InstanceId(1), + content_warning: None, + }; + + collector + .data_source + .expect_read_site_from_instance_id() + .return_once(move |_| Ok(Some(site))); + + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![], + send_community_followers_of: None, + send_all_instances: true, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert_eq!(result.len(), 1); + assert_eq!(result[0], site_inbox); + } + + #[tokio::test] + async fn test_get_inbox_urls_community_followers() { + let mut collector = setup_collector(); + let community_id = CommunityId(1); + let url1 = "https://follower1.example.com/inbox"; + let url2 = "https://follower2.example.com/inbox"; + + collector + .data_source + .expect_get_instance_followed_community_inboxes() + .return_once(move |_, _| { + Ok(vec![ + (community_id, Url::parse(url1).unwrap().into()), + (community_id, Url::parse(url2).unwrap().into()), + ]) + }); + + collector.update_communities().await.unwrap(); + + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![], + send_community_followers_of: Some(community_id), + send_all_instances: false, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert_eq!(result.len(), 2); + assert!(result.contains(&Url::parse(url1).unwrap())); + assert!(result.contains(&Url::parse(url2).unwrap())); + } + + #[tokio::test] + async fn test_get_inbox_urls_send_inboxes() { + let mut collector = setup_collector(); + collector.domain = "example.com".to_string(); + let inbox_user_1 = Url::parse("https://example.com/user1/inbox").unwrap(); + let inbox_user_2 = Url::parse("https://example.com/user2/inbox").unwrap(); + let other_domain_inbox = Url::parse("https://other-domain.com/user3/inbox").unwrap(); + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![ + Some(inbox_user_1.clone().into()), + Some(inbox_user_2.clone().into()), + Some(other_domain_inbox.clone().into()), + ], + send_community_followers_of: None, + send_all_instances: false, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert_eq!(result.len(), 2); + assert!(result.contains(&inbox_user_1)); + assert!(result.contains(&inbox_user_2)); + assert!(!result.contains(&other_domain_inbox)); + } + + #[tokio::test] + async fn test_get_inbox_urls_combined() { + let mut collector = setup_collector(); + collector.domain = "example.com".to_string(); + let community_id = CommunityId(1); + + let site_inbox = Url::parse("https://example.com/site_inbox").unwrap(); + let site = Site { + id: SiteId(1), + name: "Test Site".to_string(), + sidebar: None, + published: Utc::now(), + updated: None, + icon: None, + banner: None, + description: None, + actor_id: Url::parse("https://example.com/site").unwrap().into(), + last_refreshed_at: Utc::now(), + inbox_url: site_inbox.clone().into(), + private_key: None, + public_key: "test_key".to_string(), + instance_id: InstanceId(1), + content_warning: None, + }; + + collector + .data_source + .expect_read_site_from_instance_id() + .return_once(move |_| Ok(Some(site))); + + let subdomain_inbox = "https://follower.example.com/inbox"; + collector + .data_source + .expect_get_instance_followed_community_inboxes() + .return_once(move |_, _| { + Ok(vec![( + community_id, + Url::parse(subdomain_inbox).unwrap().into(), + )]) + }); + + collector.update_communities().await.unwrap(); + let user1_inbox = Url::parse("https://example.com/user1/inbox").unwrap(); + let user2_inbox = Url::parse("https://other-domain.com/user2/inbox").unwrap(); + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![ + Some(user1_inbox.clone().into()), + Some(user2_inbox.clone().into()), + ], + send_community_followers_of: Some(community_id), + send_all_instances: true, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert_eq!(result.len(), 3); + assert!(result.contains(&site_inbox)); + assert!(result.contains(&Url::parse(subdomain_inbox).unwrap())); + assert!(result.contains(&user1_inbox)); + assert!(!result.contains(&user2_inbox)); + } + + #[tokio::test] + async fn test_update_communities() { + let mut collector = setup_collector(); + let community_id1 = CommunityId(1); + let community_id2 = CommunityId(2); + let community_id3 = CommunityId(3); + + let user1_inbox_str = "https://follower1.example.com/inbox"; + let user1_inbox = Url::parse(user1_inbox_str).unwrap(); + let user2_inbox_str = "https://follower2.example.com/inbox"; + let user2_inbox = Url::parse(user2_inbox_str).unwrap(); + let user3_inbox_str = "https://follower3.example.com/inbox"; + let user3_inbox = Url::parse(user3_inbox_str).unwrap(); + + collector + .data_source + .expect_get_instance_followed_community_inboxes() + .times(2) + .returning(move |_, last_fetch| { + if last_fetch == Utc.timestamp_nanos(0) { + Ok(vec![ + (community_id1, Url::parse(user1_inbox_str).unwrap().into()), + (community_id2, Url::parse(user2_inbox_str).unwrap().into()), + ]) + } else { + Ok(vec![( + community_id3, + Url::parse(user3_inbox_str).unwrap().into(), + )]) + } + }); + + // First update + collector.update_communities().await.unwrap(); + assert_eq!(collector.followed_communities.len(), 2); + assert!(collector.followed_communities[&community_id1].contains(&user1_inbox)); + assert!(collector.followed_communities[&community_id2].contains(&user2_inbox)); + + // Simulate time passing + collector.last_full_communities_fetch = Utc::now() - chrono::TimeDelta::try_minutes(3).unwrap(); + collector.last_incremental_communities_fetch = + Utc::now() - chrono::TimeDelta::try_minutes(3).unwrap(); + + // Second update (incremental) + collector.update_communities().await.unwrap(); + assert_eq!(collector.followed_communities.len(), 3); + assert!(collector.followed_communities[&community_id1].contains(&user1_inbox)); + assert!(collector.followed_communities[&community_id3].contains(&user3_inbox)); + assert!(collector.followed_communities[&community_id2].contains(&user2_inbox)); + } + + #[tokio::test] + async fn test_get_inbox_urls_no_duplicates() { + let mut collector = setup_collector(); + collector.domain = "example.com".to_string(); + let community_id = CommunityId(1); + let site_inbox = Url::parse("https://example.com/site_inbox").unwrap(); + let site_inbox_clone = site_inbox.clone(); + let site = Site { + id: SiteId(1), + name: "Test Site".to_string(), + sidebar: None, + published: Utc::now(), + updated: None, + icon: None, + banner: None, + description: None, + actor_id: Url::parse("https://example.com/site").unwrap().into(), + last_refreshed_at: Utc::now(), + inbox_url: site_inbox.clone().into(), + private_key: None, + public_key: "test_key".to_string(), + instance_id: InstanceId(1), + content_warning: None, + }; + + collector + .data_source + .expect_read_site_from_instance_id() + .return_once(move |_| Ok(Some(site))); + + collector + .data_source + .expect_get_instance_followed_community_inboxes() + .return_once(move |_, _| Ok(vec![(community_id, site_inbox_clone.into())])); + + collector.update_communities().await.unwrap(); + + let activity = SentActivity { + id: ActivityId(1), + ap_id: Url::parse("https://example.com/activities/1") + .unwrap() + .into(), + data: json!({}), + sensitive: false, + published: Utc::now(), + send_inboxes: vec![Some(site_inbox.into())], + send_community_followers_of: Some(community_id), + send_all_instances: true, + actor_type: ActorType::Person, + actor_apub_id: None, + }; + + let result = collector.get_inbox_urls(&activity).await.unwrap(); + assert_eq!(result.len(), 1); + assert!(result.contains(&Url::parse("https://example.com/site_inbox").unwrap())); + } +} diff --git a/crates/federate/src/lib.rs b/crates/federate/src/lib.rs index 21b9229b5..66c0a2872 100644 --- a/crates/federate/src/lib.rs +++ b/crates/federate/src/lib.rs @@ -1,6 +1,9 @@ use crate::{util::CancellableTask, worker::InstanceWorker}; use activitypub_federation::config::FederationConfig; -use lemmy_api_common::context::LemmyContext; +use lemmy_api_common::{ + context::LemmyContext, + lemmy_utils::settings::structs::FederationWorkerConfig, +}; use lemmy_db_schema::{newtypes::InstanceId, source::instance::Instance}; use lemmy_utils::error::LemmyResult; use stats::receive_print_stats; @@ -14,6 +17,8 @@ use tokio_util::sync::CancellationToken; use tracing::info; use util::FederationQueueStateWithDomain; +mod inboxes; +mod send; mod stats; mod util; mod worker; @@ -38,10 +43,15 @@ pub struct SendManager { context: FederationConfig, stats_sender: UnboundedSender, exit_print: JoinHandle<()>, + federation_worker_config: FederationWorkerConfig, } impl SendManager { - fn new(opts: Opts, context: FederationConfig) -> Self { + fn new( + opts: Opts, + context: FederationConfig, + federation_worker_config: FederationWorkerConfig, + ) -> Self { assert!(opts.process_count > 0); assert!(opts.process_index > 0); assert!(opts.process_index <= opts.process_count); @@ -56,14 +66,20 @@ impl SendManager { stats_receiver, )), context, + federation_worker_config, } } - pub fn run(opts: Opts, context: FederationConfig) -> CancellableTask { + pub fn run( + opts: Opts, + context: FederationConfig, + config: FederationWorkerConfig, + ) -> CancellableTask { CancellableTask::spawn(WORKER_EXIT_TIMEOUT, move |cancel| { let opts = opts.clone(); + let config = config.clone(); let context = context.clone(); - let mut manager = Self::new(opts, context); + let mut manager = Self::new(opts, context, config); async move { let result = manager.do_loop(cancel).await; // the loop function will only return if there is (a) an internal error (e.g. db connection @@ -120,22 +136,21 @@ impl SendManager { // create new worker let context = self.context.clone(); let stats_sender = self.stats_sender.clone(); + let federation_worker_config = self.federation_worker_config.clone(); + self.workers.insert( instance.id, CancellableTask::spawn(WORKER_EXIT_TIMEOUT, move |stop| { - // if the instance worker ends unexpectedly due to internal/db errors, this lambda is rerun by cancellabletask. + // if the instance worker ends unexpectedly due to internal/db errors, this lambda is + // rerun by cancellabletask. let instance = instance.clone(); - let req_data = context.to_request_data(); - let stats_sender = stats_sender.clone(); - async move { - InstanceWorker::init_and_loop( - instance, - req_data, - stop, - stats_sender, - ) - .await - } + InstanceWorker::init_and_loop( + instance, + context.clone(), + federation_worker_config.clone(), + stop, + stats_sender.clone(), + ) }), ); } else if !should_federate { @@ -214,7 +229,14 @@ mod test { .app_data(context.clone()) .build() .await?; + let concurrent_sends_per_instance = std::env::var("LEMMY_TEST_FEDERATION_CONCURRENT_SENDS") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(1); + let federation_worker_config = FederationWorkerConfig { + concurrent_sends_per_instance, + }; let pool = &mut context.pool(); let instances = vec![ Instance::read_or_create(pool, "alpha.com".to_string()).await?, @@ -222,7 +244,7 @@ mod test { Instance::read_or_create(pool, "gamma.com".to_string()).await?, ]; - let send_manager = SendManager::new(opts, federation_config); + let send_manager = SendManager::new(opts, federation_config, federation_worker_config); Ok(Self { send_manager, context, diff --git a/crates/federate/src/send.rs b/crates/federate/src/send.rs new file mode 100644 index 000000000..01d620eb0 --- /dev/null +++ b/crates/federate/src/send.rs @@ -0,0 +1,148 @@ +use crate::util::get_actor_cached; +use activitypub_federation::{ + activity_sending::SendActivityTask, + config::Data, + protocol::context::WithContext, +}; +use anyhow::{Context, Result}; +use chrono::{DateTime, Utc}; +use lemmy_api_common::{context::LemmyContext, federate_retry_sleep_duration}; +use lemmy_apub::{activity_lists::SharedInboxActivities, FEDERATION_CONTEXT}; +use lemmy_db_schema::{newtypes::ActivityId, source::activity::SentActivity}; +use reqwest::Url; +use std::ops::Deref; +use tokio::{sync::mpsc::UnboundedSender, time::sleep}; +use tokio_util::sync::CancellationToken; + +#[derive(Debug, Eq)] +pub(crate) struct SendSuccessInfo { + pub activity_id: ActivityId, + pub published: Option>, + // true if the activity was skipped because the target instance is not interested in this + // activity + pub was_skipped: bool, +} +impl PartialEq for SendSuccessInfo { + fn eq(&self, other: &Self) -> bool { + self.activity_id == other.activity_id + } +} +/// order backwards because the binary heap is a max heap, and we need the smallest element to be on +/// top +impl PartialOrd for SendSuccessInfo { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} +impl Ord for SendSuccessInfo { + fn cmp(&self, other: &Self) -> std::cmp::Ordering { + other.activity_id.cmp(&self.activity_id) + } +} + +/// Represents the result of sending an activity. +/// +/// This enum is used to communicate the outcome of a send operation from a send task +/// to the main instance worker. It's designed to maintain a clean separation between +/// the send task and the main thread, allowing the send.rs file to be self-contained +/// and easier to understand. +/// +/// The use of a channel for communication (rather than shared atomic variables) was chosen +/// because: +/// 1. It keeps the send task cleanly separated with no direct interaction with the main thread. +/// 2. The failure event needs to be transferred to the main task for database updates anyway. +/// 3. The main fail_count should only be updated under certain conditions, which are best handled +/// in the main task. +/// 4. It maintains consistency in how data is communicated (all via channels rather than a mix of +/// channels and atomics). +/// 5. It simplifies concurrency management and makes the flow of data more predictable. +pub(crate) enum SendActivityResult { + Success(SendSuccessInfo), + Failure { fail_count: i32 }, +} +/// Represents a task for retrying to send an activity. +/// +/// This struct encapsulates all the necessary information and resources for attempting +/// to send an activity to multiple inbox URLs, with built-in retry logic. +pub(crate) struct SendRetryTask<'a> { + pub activity: &'a SentActivity, + pub object: &'a SharedInboxActivities, + /// Must not be empty at this point + pub inbox_urls: Vec, + /// Channel to report results back to the main instance worker + pub report: &'a mut UnboundedSender, + /// The first request will be sent immediately, but subsequent requests will be delayed + /// according to the number of previous fails + 1 + /// + /// This is a read-only immutable variable that is passed only one way, from the main + /// thread to each send task. It allows the task to determine how long to sleep initially + /// if the request fails. + pub initial_fail_count: i32, + /// For logging purposes + pub domain: String, + pub context: Data, + pub stop: CancellationToken, +} + +impl<'a> SendRetryTask<'a> { + // this function will return successfully when (a) send succeeded or (b) worker cancelled + // and will return an error if an internal error occurred (send errors cause an infinite loop) + pub async fn send_retry_loop(self) -> Result<()> { + let SendRetryTask { + activity, + object, + inbox_urls, + report, + initial_fail_count, + domain, + context, + stop, + } = self; + debug_assert!(!inbox_urls.is_empty()); + + let pool = &mut context.pool(); + let Some(actor_apub_id) = &activity.actor_apub_id else { + return Err(anyhow::anyhow!("activity is from before lemmy 0.19")); + }; + let actor = get_actor_cached(pool, activity.actor_type, actor_apub_id) + .await + .context("failed getting actor instance (was it marked deleted / removed?)")?; + + let object = WithContext::new(object.clone(), FEDERATION_CONTEXT.deref().clone()); + let requests = SendActivityTask::prepare(&object, actor.as_ref(), inbox_urls, &context).await?; + for task in requests { + // usually only one due to shared inbox + tracing::debug!("sending out {}", task); + let mut fail_count = initial_fail_count; + while let Err(e) = task.sign_and_send(&context).await { + fail_count += 1; + report.send(SendActivityResult::Failure { + fail_count, + // activity_id: activity.id, + })?; + let retry_delay = federate_retry_sleep_duration(fail_count); + tracing::info!( + "{}: retrying {:?} attempt {} with delay {retry_delay:.2?}. ({e})", + domain, + activity.id, + fail_count + ); + tokio::select! { + () = sleep(retry_delay) => {}, + () = stop.cancelled() => { + // cancel sending without reporting any result. + // the InstanceWorker needs to be careful to not hang on receive of that + // channel when cancelled (see handle_send_results) + return Ok(()); + } + } + } + } + report.send(SendActivityResult::Success(SendSuccessInfo { + activity_id: activity.id, + published: Some(activity.published), + was_skipped: false, + }))?; + Ok(()) + } +} diff --git a/crates/federate/src/util.rs b/crates/federate/src/util.rs index 60361c3c9..afbe957a5 100644 --- a/crates/federate/src/util.rs +++ b/crates/federate/src/util.rs @@ -1,7 +1,6 @@ use anyhow::{anyhow, Context, Result}; use diesel::prelude::*; use diesel_async::RunQueryDsl; -use lemmy_api_common::lemmy_utils::CACHE_DURATION_FEDERATION; use lemmy_apub::{ activity_lists::SharedInboxActivities, fetcher::{site_or_community_or_user::SiteOrCommunityOrUser, user_or_community::UserOrCommunity}, @@ -28,19 +27,28 @@ use tokio_util::sync::CancellationToken; /// Decrease the delays of the federation queue. /// Should only be used for federation tests since it significantly increases CPU and DB load of the -/// federation queue. +/// federation queue. This is intentionally a separate flag from other flags like debug_assertions, +/// since this is a invasive change we only need rarely. pub(crate) static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { std::env::var("LEMMY_TEST_FAST_FEDERATION") .map(|s| !s.is_empty()) .unwrap_or(false) }); -/// Recheck for new federation work every n seconds. +/// Recheck for new federation work every n seconds within each InstanceWorker. /// /// When the queue is processed faster than new activities are added and it reaches the current time /// with an empty batch, this is the delay the queue waits before it checks if new activities have /// been added to the sent_activities table. This delay is only applied if no federated activity -/// happens during sending activities of the last batch. +/// happens during sending activities of the last batch, which means on high-activity instances it +/// may never be used. This means that it does not affect the maximum throughput of the queue. +/// +/// +/// This is thus the interval with which tokio wakes up each of the +/// InstanceWorkers to check for new work, if the queue previously was empty. +/// If the delay is too short, the workers (one per federated instance) will wake up too +/// often and consume a lot of CPU. If the delay is long, then activities on low-traffic instances +/// will on average take delay/2 seconds to federate. pub(crate) static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { if *LEMMY_TEST_FAST_FEDERATION { Duration::from_millis(100) @@ -49,6 +57,21 @@ pub(crate) static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { } }); +/// Cache the latest activity id for a certain duration. +/// +/// This cache is common to all the instance workers and prevents there from being more than one +/// call per N seconds between each DB query to find max(activity_id). +pub(crate) static CACHE_DURATION_LATEST_ID: Lazy = Lazy::new(|| { + if *LEMMY_TEST_FAST_FEDERATION { + // in test mode, we use the same cache duration as the recheck delay so when recheck happens + // data is fresh, accelerating the time the tests take. + *WORK_FINISHED_RECHECK_DELAY + } else { + // in normal mode, we limit the query to one per second + Duration::from_secs(1) + } +}); + /// A task that will be run in an infinite loop, unless it is cancelled. /// If the task exits without being cancelled, an error will be logged and the task will be /// restarted. @@ -174,7 +197,7 @@ pub(crate) async fn get_activity_cached( pub(crate) async fn get_latest_activity_id(pool: &mut DbPool<'_>) -> Result { static CACHE: Lazy> = Lazy::new(|| { Cache::builder() - .time_to_live(CACHE_DURATION_FEDERATION) + .time_to_live(*CACHE_DURATION_LATEST_ID) .build() }); CACHE diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 25c9278aa..28f21dcc2 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -1,132 +1,192 @@ -use crate::util::{ - get_activity_cached, - get_actor_cached, - get_latest_activity_id, - FederationQueueStateWithDomain, - LEMMY_TEST_FAST_FEDERATION, - WORK_FINISHED_RECHECK_DELAY, -}; -use activitypub_federation::{ - activity_sending::SendActivityTask, - config::Data, - protocol::context::WithContext, +use crate::{ + inboxes::RealCommunityInboxCollector, + send::{SendActivityResult, SendRetryTask, SendSuccessInfo}, + util::{ + get_activity_cached, + get_latest_activity_id, + FederationQueueStateWithDomain, + WORK_FINISHED_RECHECK_DELAY, + }, }; +use activitypub_federation::config::FederationConfig; use anyhow::{Context, Result}; use chrono::{DateTime, Days, TimeZone, Utc}; -use lemmy_api_common::{context::LemmyContext, federate_retry_sleep_duration}; -use lemmy_apub::{activity_lists::SharedInboxActivities, FEDERATION_CONTEXT}; +use lemmy_api_common::{ + context::LemmyContext, + federate_retry_sleep_duration, + lemmy_utils::settings::structs::FederationWorkerConfig, +}; use lemmy_db_schema::{ - newtypes::{ActivityId, CommunityId, InstanceId}, + newtypes::ActivityId, source::{ - activity::SentActivity, federation_queue_state::FederationQueueState, instance::{Instance, InstanceForm}, - site::Site, }, - utils::naive_now, + utils::{naive_now, ActualDbPool, DbPool}, }; -use lemmy_db_views_actor::structs::CommunityFollowerView; -use once_cell::sync::Lazy; -use reqwest::Url; -use std::{ - collections::{HashMap, HashSet}, - ops::{Add, Deref}, - time::Duration, +use std::{collections::BinaryHeap, ops::Add, time::Duration}; +use tokio::{ + sync::mpsc::{self, UnboundedSender}, + time::sleep, }; -use tokio::{sync::mpsc::UnboundedSender, time::sleep}; use tokio_util::sync::CancellationToken; -use tracing::{debug, info, trace, warn}; -/// Check whether to save state to db every n sends if there's no failures (during failures state is -/// saved after every attempt). This determines the batch size for loop_batch. After a batch ends -/// and SAVE_STATE_EVERY_TIME has passed, the federation_queue_state is updated in the DB. -static CHECK_SAVE_STATE_EVERY_IT: i64 = 100; /// Save state to db after this time has passed since the last state (so if the server crashes or is /// SIGKILLed, less than X seconds of activities are resent) +#[cfg(not(test))] static SAVE_STATE_EVERY_TIME: Duration = Duration::from_secs(60); -/// interval with which new additions to community_followers are queried. +#[cfg(test)] +/// in test mode, we want it to save state and send it to print_stats after every send +static SAVE_STATE_EVERY_TIME: Duration = Duration::from_secs(0); +/// Maximum number of successful sends to allow out of order +const MAX_SUCCESSFULS: usize = 1000; + +/// in prod mode, try to collect multiple send results at the same time to reduce load +#[cfg(not(test))] +static MIN_ACTIVITY_SEND_RESULTS_TO_HANDLE: usize = 4; +#[cfg(test)] +static MIN_ACTIVITY_SEND_RESULTS_TO_HANDLE: usize = 0; + /// -/// The first time some user on an instance follows a specific remote community (or, more precisely: -/// the first time a (followed_community_id, follower_inbox_url) tuple appears), this delay limits -/// the maximum time until the follow actually results in activities from that community id being -/// sent to that inbox url. This delay currently needs to not be too small because the DB load is -/// currently fairly high because of the current structure of storing inboxes for every person, not -/// having a separate list of shared_inboxes, and the architecture of having every instance queue be -/// fully separate. (see https://github.com/LemmyNet/lemmy/issues/3958) -static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = Lazy::new(|| { - if *LEMMY_TEST_FAST_FEDERATION { - chrono::TimeDelta::try_seconds(1).expect("TimeDelta out of bounds") - } else { - chrono::TimeDelta::try_minutes(2).expect("TimeDelta out of bounds") - } -}); -/// The same as FOLLOW_ADDITIONS_RECHECK_DELAY, but triggering when the last person on an instance -/// unfollows a specific remote community. This is expected to happen pretty rarely and updating it -/// in a timely manner is not too important. -static FOLLOW_REMOVALS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::TimeDelta::try_hours(1).expect("TimeDelta out of bounds")); +/// SendManager --(has many)--> InstanceWorker --(has many)--> SendRetryTask +/// | | | +/// -----|------create worker -> loop activities--create task-> send activity +/// | | vvvv +/// | | fail or success +/// | | <-report result-- | +/// | <---order and aggrate results--- | +/// | <---send stats--- | | +/// filter and print stats | | pub(crate) struct InstanceWorker { instance: Instance, - // load site lazily because if an instance is first seen due to being on allowlist, - // the corresponding row in `site` may not exist yet since that is only added once - // `fetch_instance_actor_for_object` is called. - // (this should be unlikely to be relevant outside of the federation tests) - site_loaded: bool, - site: Option, - followed_communities: HashMap>, stop: CancellationToken, - context: Data, - stats_sender: UnboundedSender, - last_full_communities_fetch: DateTime, - last_incremental_communities_fetch: DateTime, + federation_lib_config: FederationConfig, + federation_worker_config: FederationWorkerConfig, state: FederationQueueState, last_state_insert: DateTime, + pool: ActualDbPool, + inbox_collector: RealCommunityInboxCollector, + // regularily send stats back to the SendManager + stats_sender: UnboundedSender, + // each HTTP send will report back to this channel concurrently + receive_send_result: mpsc::UnboundedReceiver, + // this part of the channel is cloned and passed to the SendRetryTasks + report_send_result: mpsc::UnboundedSender, + // activities that have been successfully sent but + // that are not the lowest number and thus can't be written to the database yet + successfuls: BinaryHeap, + // number of activities that currently have a task spawned to send it + in_flight: i32, } impl InstanceWorker { pub(crate) async fn init_and_loop( instance: Instance, - context: Data, + config: FederationConfig, + federation_worker_config: FederationWorkerConfig, stop: CancellationToken, stats_sender: UnboundedSender, ) -> Result<(), anyhow::Error> { - let mut pool = context.pool(); - let state = FederationQueueState::load(&mut pool, instance.id).await?; + let pool = config.to_request_data().inner_pool().clone(); + let state = FederationQueueState::load(&mut DbPool::Pool(&pool), instance.id).await?; + let (report_send_result, receive_send_result) = + tokio::sync::mpsc::unbounded_channel::(); let mut worker = InstanceWorker { + inbox_collector: RealCommunityInboxCollector::new_real( + pool.clone(), + instance.id, + instance.domain.clone(), + ), + federation_worker_config, instance, - site_loaded: false, - site: None, - followed_communities: HashMap::new(), stop, - context, + federation_lib_config: config, stats_sender, - last_full_communities_fetch: Utc.timestamp_nanos(0), - last_incremental_communities_fetch: Utc.timestamp_nanos(0), state, last_state_insert: Utc.timestamp_nanos(0), + pool, + receive_send_result, + report_send_result, + successfuls: BinaryHeap::::new(), + in_flight: 0, }; + worker.loop_until_stopped().await } /// loop fetch new activities from db and send them to the inboxes of the given instances /// this worker only returns if (a) there is an internal error or (b) the cancellation token is /// cancelled (graceful exit) - pub(crate) async fn loop_until_stopped(&mut self) -> Result<(), anyhow::Error> { - debug!("Starting federation worker for {}", self.instance.domain); - let save_state_every = chrono::Duration::from_std(SAVE_STATE_EVERY_TIME).expect("not negative"); - - self.update_communities().await?; + async fn loop_until_stopped(&mut self) -> Result<()> { self.initial_fail_sleep().await?; + let (mut last_sent_id, mut newest_id) = self.get_latest_ids().await?; + while !self.stop.is_cancelled() { - self.loop_batch().await?; - if self.stop.is_cancelled() { - break; + // check if we need to wait for a send to finish before sending the next one + // we wait if (a) the last request failed, only if a request is already in flight (not at the + // start of the loop) or (b) if we have too many successfuls in memory or (c) if we have + // too many in flight + let need_wait_for_event = (self.in_flight != 0 && self.state.fail_count > 0) + || self.successfuls.len() >= MAX_SUCCESSFULS + || i64::from(self.in_flight) >= self.federation_worker_config.concurrent_sends_per_instance; + if need_wait_for_event || self.receive_send_result.len() > MIN_ACTIVITY_SEND_RESULTS_TO_HANDLE + { + // if len() > 0 then this does not block and allows us to write to db more often + // if len is 0 then this means we wait for something to change our above conditions, + // which can only happen by an event sent into the channel + self.handle_send_results().await?; + // handle_send_results does not guarantee that we are now in a condition where we want to + // send a new one, so repeat this check until the if no longer applies + continue; } - if (Utc::now() - self.last_state_insert) > save_state_every { - self.save_and_send_state().await?; + + // send a new activity if there is one + self.inbox_collector.update_communities().await?; + let next_id_to_send = ActivityId(last_sent_id.0 + 1); + { + // sanity check: calculate next id to send based on the last id and the in flight requests + let expected_next_id = self.state.last_successful_id.map(|last_successful_id| { + last_successful_id.0 + (self.successfuls.len() as i64) + i64::from(self.in_flight) + 1 + }); + // compare to next id based on incrementing + if expected_next_id != Some(next_id_to_send.0) { + anyhow::bail!( + "{}: next id to send is not as expected: {:?} != {:?}", + self.instance.domain, + expected_next_id, + next_id_to_send + ) + } } - self.update_communities().await?; + + if next_id_to_send > newest_id { + // lazily fetch latest id only if we have cought up + newest_id = self.get_latest_ids().await?.1; + if next_id_to_send > newest_id { + if next_id_to_send > ActivityId(newest_id.0 + 1) { + tracing::error!( + "{}: next send id {} is higher than latest id {}+1 in database (did the db get cleared?)", + self.instance.domain, + next_id_to_send.0, + newest_id.0 + ); + } + // no more work to be done, wait before rechecking + tokio::select! { + () = sleep(*WORK_FINISHED_RECHECK_DELAY) => {}, + () = self.stop.cancelled() => { + tracing::debug!("cancelled worker loop while waiting for new work") + } + } + continue; + } + } + self.in_flight += 1; + last_sent_id = next_id_to_send; + self.spawn_send_if_needed(next_id_to_send).await?; } - // final update of state in db + tracing::debug!("cancelled worker loop after send"); + + // final update of state in db on shutdown self.save_and_send_state().await?; Ok(()) } @@ -144,18 +204,27 @@ impl InstanceWorker { return Ok(()); } let remaining = required - elapsed; + tracing::debug!( + "{}: fail-sleeping for {:?} before starting queue", + self.instance.domain, + remaining + ); tokio::select! { () = sleep(remaining) => {}, - () = self.stop.cancelled() => {} + () = self.stop.cancelled() => { + tracing::debug!("cancelled worker loop during initial fail sleep") + } } } Ok(()) } - /// send out a batch of CHECK_SAVE_STATE_EVERY_IT activities - async fn loop_batch(&mut self) -> Result<()> { - let latest_id = get_latest_activity_id(&mut self.context.pool()).await?; - let mut id = if let Some(id) = self.state.last_successful_id { - id + + /// return the last successfully sent id and the newest activity id in the database + /// sets last_successful_id in database if it's the first time this instance is seen + async fn get_latest_ids(&mut self) -> Result<(ActivityId, ActivityId)> { + let latest_id = get_latest_activity_id(&mut self.pool()).await?; + let last = if let Some(last) = self.state.last_successful_id { + last } else { // this is the initial creation (instance first seen) of the federation queue for this // instance @@ -166,203 +235,542 @@ impl InstanceWorker { self.save_and_send_state().await?; latest_id }; - if id >= latest_id { - if id > latest_id { - tracing::error!( - "{}: last successful id {} is higher than latest id {} in database (did the db get cleared?)", - self.instance.domain, - id.0, - latest_id.0 - ); - } - // no more work to be done, wait before rechecking - tokio::select! { - () = sleep(*WORK_FINISHED_RECHECK_DELAY) => {}, - () = self.stop.cancelled() => {} - } - return Ok(()); - } - let mut processed_activities = 0; - while id < latest_id - && processed_activities < CHECK_SAVE_STATE_EVERY_IT - && !self.stop.is_cancelled() - { - id = ActivityId(id.0 + 1); - processed_activities += 1; - let Some(ele) = get_activity_cached(&mut self.context.pool(), id) - .await - .context("failed reading activity from db")? - else { - debug!("{}: {:?} does not exist", self.instance.domain, id); - self.state.last_successful_id = Some(id); - continue; - }; - if let Err(e) = self.send_retry_loop(&ele.0, &ele.1).await { - warn!( - "sending {} errored internally, skipping activity: {:?}", - ele.0.ap_id, e - ); - } - if self.stop.is_cancelled() { + Ok((last, latest_id)) + } + + async fn handle_send_results(&mut self) -> Result<(), anyhow::Error> { + let mut force_write = false; + let mut events = Vec::new(); + // Wait for at least one event but if there's multiple handle them all. + // We need to listen to the cancel event here as well in order to prevent a hang on shutdown: + // If the SendRetryTask gets cancelled, it immediately exits without reporting any state. + // So if the worker is waiting for a send result and all SendRetryTask gets cancelled, this recv + // could hang indefinitely otherwise. The tasks will also drop their handle of + // report_send_result which would cause the recv_many method to return 0 elements, but since + // InstanceWorker holds a copy of the send result channel as well, that won't happen. + tokio::select! { + _ = self.receive_send_result.recv_many(&mut events, 1000) => {}, + () = self.stop.cancelled() => { + tracing::debug!("cancelled worker loop while waiting for send results"); return Ok(()); } - // send success! - self.state.last_successful_id = Some(id); - self.state.last_successful_published_time = Some(ele.0.published); - self.state.fail_count = 0; + } + for event in events { + match event { + SendActivityResult::Success(s) => { + self.in_flight -= 1; + if !s.was_skipped { + self.state.fail_count = 0; + self.mark_instance_alive().await?; + } + self.successfuls.push(s); + } + SendActivityResult::Failure { fail_count, .. } => { + if fail_count > self.state.fail_count { + // override fail count - if multiple activities are currently sending this value may get + // conflicting info but that's fine. + // This needs to be this way, all alternatives would be worse. The reason is that if 10 + // simultaneous requests fail within a 1s period, we don't want the next retry to be + // exponentially 2**10 s later. Any amount of failures within a fail-sleep period should + // only count as one failure. + + self.state.fail_count = fail_count; + self.state.last_retry = Some(Utc::now()); + force_write = true; + } + } + } + } + self.pop_successfuls_and_write(force_write).await?; + Ok(()) + } + async fn mark_instance_alive(&mut self) -> Result<()> { + // Activity send successful, mark instance as alive if it hasn't been updated in a while. + let updated = self.instance.updated.unwrap_or(self.instance.published); + if updated.add(Days::new(1)) < Utc::now() { + self.instance.updated = Some(Utc::now()); + + let form = InstanceForm::builder() + .domain(self.instance.domain.clone()) + .updated(Some(naive_now())) + .build(); + Instance::update(&mut self.pool(), self.instance.id, form).await?; + } + Ok(()) + } + /// Checks that sequential activities `last_successful_id + 1`, `last_successful_id + 2` etc have + /// been sent successfully. In that case updates `last_successful_id` and saves the state to the + /// database if the time since the last save is greater than `SAVE_STATE_EVERY_TIME`. + async fn pop_successfuls_and_write(&mut self, force_write: bool) -> Result<()> { + let Some(mut last_id) = self.state.last_successful_id else { + tracing::warn!( + "{} should be impossible: last successful id is None", + self.instance.domain + ); + return Ok(()); + }; + tracing::debug!( + "{} last: {:?}, next: {:?}, currently in successfuls: {:?}", + self.instance.domain, + last_id, + self.successfuls.peek(), + self.successfuls.iter() + ); + while self + .successfuls + .peek() + .map(|a| a.activity_id == ActivityId(last_id.0 + 1)) + .unwrap_or(false) + { + let next = self + .successfuls + .pop() + .context("peek above ensures pop has value")?; + last_id = next.activity_id; + self.state.last_successful_id = Some(next.activity_id); + self.state.last_successful_published_time = next.published; + } + + let save_state_every = chrono::Duration::from_std(SAVE_STATE_EVERY_TIME).expect("not negative"); + if force_write || (Utc::now() - self.last_state_insert) > save_state_every { + self.save_and_send_state().await?; } Ok(()) } - // this function will return successfully when (a) send succeeded or (b) worker cancelled - // and will return an error if an internal error occurred (send errors cause an infinite loop) - async fn send_retry_loop( - &mut self, - activity: &SentActivity, - object: &SharedInboxActivities, - ) -> Result<()> { + /// we collect the relevant inboxes in the main instance worker task, and only spawn the send task + /// if we have inboxes to send to this limits CPU usage and reduces overhead for the (many) + /// cases where we don't have any inboxes + async fn spawn_send_if_needed(&mut self, activity_id: ActivityId) -> Result<()> { + let Some(ele) = get_activity_cached(&mut self.pool(), activity_id) + .await + .context("failed reading activity from db")? + else { + tracing::debug!("{}: {:?} does not exist", self.instance.domain, activity_id); + self + .report_send_result + .send(SendActivityResult::Success(SendSuccessInfo { + activity_id, + published: None, + was_skipped: true, + }))?; + return Ok(()); + }; + let activity = &ele.0; let inbox_urls = self + .inbox_collector .get_inbox_urls(activity) .await .context("failed figuring out inbox urls")?; if inbox_urls.is_empty() { - trace!("{}: {:?} no inboxes", self.instance.domain, activity.id); - self.state.last_successful_id = Some(activity.id); - self.state.last_successful_published_time = Some(activity.published); + // this is the case when the activity is not relevant to this receiving instance (e.g. no user + // subscribed to the relevant community) + tracing::debug!("{}: {:?} no inboxes", self.instance.domain, activity.id); + self + .report_send_result + .send(SendActivityResult::Success(SendSuccessInfo { + activity_id, + // it would be valid here to either return None or Some(activity.published). The published + // time is only used for stats pages that track federation delay. None can be a bit + // misleading because if you look at / chart the published time for federation from a + // large to a small instance that's only subscribed to a few small communities, + // then it will show the last published time as a days ago even though + // federation is up to date. + published: Some(activity.published), + was_skipped: true, + }))?; return Ok(()); } - let Some(actor_apub_id) = &activity.actor_apub_id else { - return Ok(()); // activity was inserted before persistent queue was activated - }; - let actor = get_actor_cached(&mut self.context.pool(), activity.actor_type, actor_apub_id) - .await - .context("failed getting actor instance (was it marked deleted / removed?)")?; - - let object = WithContext::new(object.clone(), FEDERATION_CONTEXT.deref().clone()); - let inbox_urls = inbox_urls.into_iter().collect(); - let requests = - SendActivityTask::prepare(&object, actor.as_ref(), inbox_urls, &self.context).await?; - for task in requests { - // usually only one due to shared inbox - trace!("sending out {}", task); - while let Err(e) = task.sign_and_send(&self.context).await { - self.state.fail_count += 1; - self.state.last_retry = Some(Utc::now()); - let retry_delay: Duration = federate_retry_sleep_duration(self.state.fail_count); - info!( - "{}: retrying {:?} attempt {} with delay {retry_delay:.2?}. ({e})", - self.instance.domain, activity.id, self.state.fail_count + let initial_fail_count = self.state.fail_count; + let data = self.federation_lib_config.to_request_data(); + let stop = self.stop.clone(); + let domain = self.instance.domain.clone(); + let mut report = self.report_send_result.clone(); + tokio::spawn(async move { + let res = SendRetryTask { + activity: &ele.0, + object: &ele.1, + inbox_urls, + report: &mut report, + initial_fail_count, + domain, + context: data, + stop, + } + .send_retry_loop() + .await; + if let Err(e) = res { + tracing::warn!( + "sending {} errored internally, skipping activity: {:?}", + ele.0.ap_id, + e ); - self.save_and_send_state().await?; - tokio::select! { - () = sleep(retry_delay) => {}, - () = self.stop.cancelled() => { - // save state to db and exit - return Ok(()); - } - } + // An error in this location means there is some deeper internal issue with the activity, + // for example the actor can't be loaded or similar. These issues are probably not + // solveable by retrying and would cause the federation for this instance to permanently be + // stuck in a retry loop. So we log the error and skip the activity (by reporting success to + // the worker) + report + .send(SendActivityResult::Success(SendSuccessInfo { + activity_id, + published: None, + was_skipped: true, + })) + .ok(); } - - // Activity send successful, mark instance as alive if it hasn't been updated in a while. - let updated = self.instance.updated.unwrap_or(self.instance.published); - if updated.add(Days::new(1)) < Utc::now() { - self.instance.updated = Some(Utc::now()); - - let form = InstanceForm::builder() - .domain(self.instance.domain.clone()) - .updated(Some(naive_now())) - .build(); - Instance::update(&mut self.context.pool(), self.instance.id, form).await?; - } - } + }); Ok(()) } - /// get inbox urls of sending the given activity to the given instance - /// most often this will return 0 values (if instance doesn't care about the activity) - /// or 1 value (the shared inbox) - /// > 1 values only happens for non-lemmy software - async fn get_inbox_urls(&mut self, activity: &SentActivity) -> Result> { - let mut inbox_urls: HashSet = HashSet::new(); - - if activity.send_all_instances { - if !self.site_loaded { - self.site = Site::read_from_instance_id(&mut self.context.pool(), self.instance.id).await?; - self.site_loaded = true; - } - if let Some(site) = &self.site { - // Nutomic: Most non-lemmy software wont have a site row. That means it cant handle these - // activities. So handling it like this is fine. - inbox_urls.insert(site.inbox_url.inner().clone()); - } - } - if let Some(t) = &activity.send_community_followers_of { - if let Some(urls) = self.followed_communities.get(t) { - inbox_urls.extend(urls.iter().cloned()); - } - } - inbox_urls.extend( - activity - .send_inboxes - .iter() - .filter_map(std::option::Option::as_ref) - .filter(|&u| (u.domain() == Some(&self.instance.domain))) - .map(|u| u.inner().clone()), - ); - Ok(inbox_urls) - } - - async fn update_communities(&mut self) -> Result<()> { - if (Utc::now() - self.last_full_communities_fetch) > *FOLLOW_REMOVALS_RECHECK_DELAY { - // process removals every hour - (self.followed_communities, self.last_full_communities_fetch) = self - .get_communities(self.instance.id, Utc.timestamp_nanos(0)) - .await?; - self.last_incremental_communities_fetch = self.last_full_communities_fetch; - } - if (Utc::now() - self.last_incremental_communities_fetch) > *FOLLOW_ADDITIONS_RECHECK_DELAY { - // process additions every minute - let (news, time) = self - .get_communities(self.instance.id, self.last_incremental_communities_fetch) - .await?; - self.followed_communities.extend(news); - self.last_incremental_communities_fetch = time; - } - Ok(()) - } - - /// get a list of local communities with the remote inboxes on the given instance that cares about - /// them - async fn get_communities( - &mut self, - instance_id: InstanceId, - last_fetch: DateTime, - ) -> Result<(HashMap>, DateTime)> { - let new_last_fetch = - Utc::now() - chrono::TimeDelta::try_seconds(10).expect("TimeDelta out of bounds"); // update to time before fetch to ensure overlap. subtract 10s to ensure overlap even if - // published date is not exact - Ok(( - CommunityFollowerView::get_instance_followed_community_inboxes( - &mut self.context.pool(), - instance_id, - last_fetch, - ) - .await? - .into_iter() - .fold(HashMap::new(), |mut map, (c, u)| { - map.entry(c).or_default().insert(u.into()); - map - }), - new_last_fetch, - )) - } async fn save_and_send_state(&mut self) -> Result<()> { + tracing::debug!("{}: saving and sending state", self.instance.domain); self.last_state_insert = Utc::now(); - FederationQueueState::upsert(&mut self.context.pool(), &self.state).await?; + FederationQueueState::upsert(&mut self.pool(), &self.state).await?; self.stats_sender.send(FederationQueueStateWithDomain { state: self.state.clone(), domain: self.instance.domain.clone(), })?; Ok(()) } + + fn pool(&self) -> DbPool<'_> { + DbPool::Pool(&self.pool) + } +} + +#[cfg(test)] +#[allow(clippy::unwrap_used)] +#[allow(clippy::indexing_slicing)] +mod test { + + use super::*; + use activitypub_federation::{ + http_signatures::generate_actor_keypair, + protocol::context::WithContext, + }; + use actix_web::{dev::ServerHandle, web, App, HttpResponse, HttpServer}; + use lemmy_api_common::utils::{generate_inbox_url, generate_shared_inbox_url}; + use lemmy_db_schema::{ + newtypes::DbUrl, + source::{ + activity::{ActorType, SentActivity, SentActivityForm}, + person::{Person, PersonInsertForm}, + }, + traits::Crud, + }; + use lemmy_utils::error::LemmyResult; + use reqwest::StatusCode; + use serde_json::{json, Value}; + use serial_test::serial; + use test_context::{test_context, AsyncTestContext}; + use tokio::{ + spawn, + sync::mpsc::{error::TryRecvError, unbounded_channel, UnboundedReceiver}, + }; + use tracing_test::traced_test; + use url::Url; + + struct Data { + context: activitypub_federation::config::Data, + instance: Instance, + person: Person, + stats_receiver: UnboundedReceiver, + inbox_receiver: UnboundedReceiver, + cancel: CancellationToken, + cleaned_up: bool, + wait_stop_server: ServerHandle, + is_concurrent: bool, + } + + impl Data { + async fn init() -> LemmyResult { + let context = LemmyContext::init_test_federation_config().await; + let instance = Instance::read_or_create(&mut context.pool(), "localhost".to_string()).await?; + + let actor_keypair = generate_actor_keypair()?; + let actor_id: DbUrl = Url::parse("http://local.com/u/alice")?.into(); + let person_form = PersonInsertForm { + actor_id: Some(actor_id.clone()), + private_key: (Some(actor_keypair.private_key)), + inbox_url: Some(generate_inbox_url(&actor_id)?), + shared_inbox_url: Some(generate_shared_inbox_url(context.settings())?), + ..PersonInsertForm::new("alice".to_string(), actor_keypair.public_key, instance.id) + }; + let person = Person::create(&mut context.pool(), &person_form).await?; + + let cancel = CancellationToken::new(); + let (stats_sender, stats_receiver) = unbounded_channel(); + let (inbox_sender, inbox_receiver) = unbounded_channel(); + + // listen for received activities in background + let wait_stop_server = listen_activities(inbox_sender)?; + + let concurrent_sends_per_instance = std::env::var("LEMMY_TEST_FEDERATION_CONCURRENT_SENDS") + .ok() + .and_then(|s| s.parse().ok()) + .unwrap_or(10); + + let fed_config = FederationWorkerConfig { + concurrent_sends_per_instance, + }; + spawn(InstanceWorker::init_and_loop( + instance.clone(), + context.clone(), + fed_config, + cancel.clone(), + stats_sender, + )); + // wait for startup + sleep(*WORK_FINISHED_RECHECK_DELAY).await; + + Ok(Self { + context: context.to_request_data(), + instance, + person, + stats_receiver, + inbox_receiver, + cancel, + wait_stop_server, + cleaned_up: false, + is_concurrent: concurrent_sends_per_instance > 1, + }) + } + + async fn cleanup(&mut self) -> LemmyResult<()> { + if self.cleaned_up { + return Ok(()); + } + self.cleaned_up = true; + self.cancel.cancel(); + sleep(*WORK_FINISHED_RECHECK_DELAY).await; + Instance::delete_all(&mut self.context.pool()).await?; + Person::delete(&mut self.context.pool(), self.person.id).await?; + self.wait_stop_server.stop(true).await; + Ok(()) + } + } + + /// In order to guarantee that the webserver is stopped via the cleanup function, + /// we implement a test context. + impl AsyncTestContext for Data { + async fn setup() -> Data { + Data::init().await.unwrap() + } + async fn teardown(mut self) { + self.cleanup().await.unwrap() + } + } + + #[test_context(Data)] + #[tokio::test] + #[traced_test] + #[serial] + async fn test_stats(data: &mut Data) -> LemmyResult<()> { + tracing::debug!("hello world"); + + // first receive at startup + let rcv = data.stats_receiver.recv().await.unwrap(); + tracing::debug!("received first stats"); + assert_eq!(data.instance.id, rcv.state.instance_id); + + let sent = send_activity(data.person.actor_id.clone(), &data.context, true).await?; + tracing::debug!("sent activity"); + // receive for successfully sent activity + let inbox_rcv = data.inbox_receiver.recv().await.unwrap(); + let parsed_activity = serde_json::from_str::>(&inbox_rcv)?; + assert_eq!(&sent.data, parsed_activity.inner()); + tracing::debug!("received activity"); + + let rcv = data.stats_receiver.recv().await.unwrap(); + assert_eq!(data.instance.id, rcv.state.instance_id); + assert_eq!(Some(sent.id), rcv.state.last_successful_id); + tracing::debug!("received second stats"); + + data.cleanup().await?; + + // it also sends state on shutdown + let rcv = data.stats_receiver.try_recv(); + assert!(rcv.is_ok()); + + // nothing further received + let rcv = data.stats_receiver.try_recv(); + assert_eq!(Some(TryRecvError::Disconnected), rcv.err()); + let inbox_rcv = data.inbox_receiver.try_recv(); + assert_eq!(Some(TryRecvError::Disconnected), inbox_rcv.err()); + + Ok(()) + } + + #[test_context(Data)] + #[tokio::test] + #[traced_test] + #[serial] + async fn test_send_40(data: &mut Data) -> LemmyResult<()> { + tracing::debug!("hello world"); + + // first receive at startup + let rcv = data.stats_receiver.recv().await.unwrap(); + tracing::debug!("received first stats"); + assert_eq!(data.instance.id, rcv.state.instance_id); + // assert_eq!(Some(ActivityId(0)), rcv.state.last_successful_id); + // let last_id_before = rcv.state.last_successful_id.unwrap(); + let mut sent = Vec::new(); + for _ in 0..40 { + sent.push(send_activity(data.person.actor_id.clone(), &data.context, false).await?); + } + sleep(2 * *WORK_FINISHED_RECHECK_DELAY).await; + tracing::debug!("sent activity"); + compare_sent_with_receive(data, sent).await?; + + Ok(()) + } + + #[test_context(Data)] + #[tokio::test] + #[traced_test] + #[serial] + /// this test sends 15 activities, waits and checks they have all been received, then sends 50, + /// etc + async fn test_send_15_20_30(data: &mut Data) -> LemmyResult<()> { + tracing::debug!("hello world"); + + // first receive at startup + let rcv = data.stats_receiver.recv().await.unwrap(); + tracing::debug!("received first stats"); + assert_eq!(data.instance.id, rcv.state.instance_id); + // assert_eq!(Some(ActivityId(0)), rcv.state.last_successful_id); + // let last_id_before = rcv.state.last_successful_id.unwrap(); + let counts = vec![15, 20, 35]; + for count in counts { + tracing::debug!("sending {} activities", count); + let mut sent = Vec::new(); + for _ in 0..count { + sent.push(send_activity(data.person.actor_id.clone(), &data.context, false).await?); + } + sleep(2 * *WORK_FINISHED_RECHECK_DELAY).await; + tracing::debug!("sent activity"); + compare_sent_with_receive(data, sent).await?; + } + + Ok(()) + } + + #[test_context(Data)] + #[tokio::test] + #[serial] + async fn test_update_instance(data: &mut Data) -> LemmyResult<()> { + let form = InstanceForm::builder() + .domain(data.instance.domain.clone()) + .updated(None) + .build(); + Instance::update(&mut data.context.pool(), data.instance.id, form).await?; + + send_activity(data.person.actor_id.clone(), &data.context, true).await?; + data.inbox_receiver.recv().await.unwrap(); + + let instance = + Instance::read_or_create(&mut data.context.pool(), data.instance.domain.clone()).await?; + + assert!(instance.updated.is_some()); + + data.cleanup().await?; + + Ok(()) + } + + fn listen_activities(inbox_sender: UnboundedSender) -> LemmyResult { + let run = HttpServer::new(move || { + App::new() + .app_data(actix_web::web::Data::new(inbox_sender.clone())) + .route( + "/inbox", + web::post().to( + |inbox_sender: actix_web::web::Data>, body: String| async move { + tracing::debug!("received activity: {:?}", body); + inbox_sender.send(body.clone()).unwrap(); + HttpResponse::new(StatusCode::OK) + }, + ), + ) + }) + .bind(("127.0.0.1", 8085))? + .run(); + let handle = run.handle(); + tokio::spawn(async move { + run.await.unwrap(); + /*select! { + _ = run => {}, + _ = cancel.cancelled() => { } + }*/ + }); + Ok(handle) + } + + async fn send_activity( + actor_id: DbUrl, + context: &LemmyContext, + wait: bool, + ) -> LemmyResult { + // create outgoing activity + let data = json!({ + "actor": "http://ds9.lemmy.ml/u/lemmy_alpha", + "object": "http://ds9.lemmy.ml/comment/1", + "audience": "https://enterprise.lemmy.ml/c/tenforward", + "type": "Like", + "id": format!("http://ds9.lemmy.ml/activities/like/{}", uuid::Uuid::new_v4()), + }); + let form = SentActivityForm { + ap_id: Url::parse(&format!( + "http://local.com/activity/{}", + uuid::Uuid::new_v4() + ))? + .into(), + data, + sensitive: false, + send_inboxes: vec![Some(Url::parse("http://localhost:8085/inbox")?.into())], + send_all_instances: false, + send_community_followers_of: None, + actor_type: ActorType::Person, + actor_apub_id: actor_id, + }; + let sent = SentActivity::create(&mut context.pool(), form).await?; + + if wait { + sleep(*WORK_FINISHED_RECHECK_DELAY * 2).await; + } + + Ok(sent) + } + async fn compare_sent_with_receive(data: &mut Data, mut sent: Vec) -> Result<()> { + let check_order = !data.is_concurrent; // allow out-of order receiving when running parallel + let mut received = Vec::new(); + for _ in 0..sent.len() { + let inbox_rcv = data.inbox_receiver.recv().await.unwrap(); + let parsed_activity = serde_json::from_str::>(&inbox_rcv)?; + received.push(parsed_activity); + } + if !check_order { + // sort by id + received.sort_by(|a, b| { + a.inner()["id"] + .as_str() + .unwrap() + .cmp(b.inner()["id"].as_str().unwrap()) + }); + sent.sort_by(|a, b| { + a.data["id"] + .as_str() + .unwrap() + .cmp(b.data["id"].as_str().unwrap()) + }); + } + // receive for successfully sent activity + for i in 0..sent.len() { + let sent_activity = &sent[i]; + let received_activity = received[i].inner(); + assert_eq!(&sent_activity.data, received_activity); + tracing::debug!("received activity"); + } + Ok(()) + } } diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index 75aa56a88..dcacc37b6 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -43,12 +43,8 @@ pub struct Settings { #[default(None)] #[doku(skip)] pub opentelemetry_url: Option, - /// The number of activitypub federation workers that can be in-flight concurrently - #[default(0)] - pub worker_count: usize, - /// The number of activitypub federation retry workers that can be in-flight concurrently - #[default(0)] - pub retry_count: usize, + #[default(Default::default())] + pub federation: FederationWorkerConfig, // Prometheus configuration. #[default(None)] #[doku(example = "Some(Default::default())")] @@ -237,3 +233,14 @@ pub struct PrometheusConfig { #[doku(example = "10002")] pub port: i32, } + +#[derive(Debug, Deserialize, Serialize, Clone, SmartDefault, Document)] +#[serde(default)] +// named federation"worker"config to disambiguate from the activitypub library configuration +pub struct FederationWorkerConfig { + /// Limit to the number of concurrent outgoing federation requests per target instance. + /// Set this to a higher value than 1 (e.g. 6) only if you have a huge instance (>10 activities + /// per second) and if a receiving instance is not keeping up. + #[default(1)] + pub concurrent_sends_per_instance: i64, +} diff --git a/scripts/test.sh b/scripts/test.sh index 9bb6acaa8..04cc94f9d 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -14,6 +14,7 @@ source scripts/start_dev_db.sh # so to load the config we need to traverse to the repo root export LEMMY_CONFIG_LOCATION=../../config/config.hjson export RUST_BACKTRACE=1 +export LEMMY_TEST_FAST_FEDERATION=1 # by default, the persistent federation queue has delays in the scale of 30s-5min if [ -n "$PACKAGE" ]; then diff --git a/src/lib.rs b/src/lib.rs index 74c05deaa..3c3633b75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -233,6 +233,7 @@ pub async fn start_lemmy_server(args: CmdArgs) -> LemmyResult<()> { process_count: args.federate_process_count, }, cfg, + SETTINGS.federation.clone(), ) }); let mut interrupt = tokio::signal::unix::signal(SignalKind::interrupt())?; From 3d80ac2ebbbb890e7ed180f58445cecaa7143a2b Mon Sep 17 00:00:00 2001 From: Darren M Date: Sun, 21 Jul 2024 19:33:42 -0700 Subject: [PATCH 21/69] Fix tls pool (#4910) * Cargo: add rustls as a dependency * install tls provider in main * Cargo: re-define rustls dependency --- Cargo.toml | 1 + crates/db_schema/src/utils.rs | 4 ---- src/main.rs | 6 ++++++ 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 461a6cc84..ca0598f82 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -203,6 +203,7 @@ opentelemetry = { workspace = true, optional = true } console-subscriber = { version = "0.3.0", optional = true } opentelemetry-otlp = { version = "0.12.0", optional = true } pict-rs = { version = "0.5.15", optional = true } +rustls = { workspace = true } tokio.workspace = true actix-cors = "0.7.0" futures-util = { workspace = true } diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index ec9f9ded7..bcddce19b 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -327,10 +327,6 @@ fn establish_connection(config: &str) -> BoxFuture LemmyResult<()> { init_logging(&SETTINGS.opentelemetry_url)?; let args = CmdArgs::parse(); + rustls::crypto::ring::default_provider() + .install_default() + .expect("Failed to install rustls crypto provider"); + #[cfg(not(feature = "embed-pictrs"))] start_lemmy_server(args).await?; #[cfg(feature = "embed-pictrs")] From 572a42d880f1acf1635ce3a877852b02317bd8df Mon Sep 17 00:00:00 2001 From: Nutomic Date: Mon, 22 Jul 2024 15:58:50 +0200 Subject: [PATCH 22/69] Change type of concurrent sends in config (#4914) --- Cargo.lock | 1 + crates/federate/src/worker.rs | 4 ++-- crates/utils/src/settings/structs.rs | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e1b90a9f0..30b707f44 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3075,6 +3075,7 @@ dependencies = [ "reqwest 0.11.27", "reqwest-middleware 0.2.5", "reqwest-tracing 0.4.8", + "rustls 0.23.10", "serde_json", "serial_test", "tokio", diff --git a/crates/federate/src/worker.rs b/crates/federate/src/worker.rs index 28f21dcc2..f6e70d846 100644 --- a/crates/federate/src/worker.rs +++ b/crates/federate/src/worker.rs @@ -76,7 +76,7 @@ pub(crate) struct InstanceWorker { // that are not the lowest number and thus can't be written to the database yet successfuls: BinaryHeap, // number of activities that currently have a task spawned to send it - in_flight: i32, + in_flight: i8, } impl InstanceWorker { @@ -127,7 +127,7 @@ impl InstanceWorker { // too many in flight let need_wait_for_event = (self.in_flight != 0 && self.state.fail_count > 0) || self.successfuls.len() >= MAX_SUCCESSFULS - || i64::from(self.in_flight) >= self.federation_worker_config.concurrent_sends_per_instance; + || self.in_flight >= self.federation_worker_config.concurrent_sends_per_instance; if need_wait_for_event || self.receive_send_result.len() > MIN_ACTIVITY_SEND_RESULTS_TO_HANDLE { // if len() > 0 then this does not block and allows us to write to db more often diff --git a/crates/utils/src/settings/structs.rs b/crates/utils/src/settings/structs.rs index dcacc37b6..547ae20d9 100644 --- a/crates/utils/src/settings/structs.rs +++ b/crates/utils/src/settings/structs.rs @@ -242,5 +242,5 @@ pub struct FederationWorkerConfig { /// Set this to a higher value than 1 (e.g. 6) only if you have a huge instance (>10 activities /// per second) and if a receiving instance is not keeping up. #[default(1)] - pub concurrent_sends_per_instance: i64, + pub concurrent_sends_per_instance: i8, } From db390a2f3ae186861904eb160e52bb2002549900 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> Date: Tue, 23 Jul 2024 15:05:19 +0000 Subject: [PATCH 23/69] Make eligible enums convertable to static strs (#4915) * Make eligible enums convertable to static strs * Run cargo fmt * Remove unnecessary derives --- Cargo.lock | 762 +++++++++--------- Cargo.toml | 3 +- crates/apub/Cargo.toml | 2 +- .../activities/community/lock_page.rs | 4 +- crates/apub/src/protocol/activities/mod.rs | 2 +- .../src/protocol/activities/voting/vote.rs | 2 +- crates/db_schema/Cargo.toml | 1 - crates/db_schema/src/lib.rs | 2 +- crates/db_views_actor/Cargo.toml | 1 - crates/db_views_actor/src/person_view.rs | 2 +- crates/utils/Cargo.toml | 1 - crates/utils/src/error.rs | 2 +- crates/utils/src/rate_limit/rate_limiter.rs | 4 +- 13 files changed, 400 insertions(+), 388 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 30b707f44..c3466f662 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -69,7 +69,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "bytes", "futures-core", "futures-sink", @@ -97,9 +97,9 @@ dependencies = [ [[package]] name = "actix-form-data" -version = "0.7.0-beta.7" +version = "0.7.0-beta.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2355a841a5d9a6c616d6a4f31336064116d206e6c1830de22730f983613a05" +checksum = "6a4f1e31610d53f56cb38c07fd8e10033e8462091528f3af6970f81a27ef9bba" dependencies = [ "actix-multipart", "actix-web", @@ -113,9 +113,9 @@ dependencies = [ [[package]] name = "actix-http" -version = "3.7.0" +version = "3.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eb9843d84c775696c37d9a418bbb01b932629d01870722c0f13eb3f95e2536d" +checksum = "3ae682f693a9cd7b058f2b0b5d9a6d7728a8555779bedbbc35dd88528611d020" dependencies = [ "actix-codec", "actix-rt", @@ -124,7 +124,7 @@ dependencies = [ "actix-utils", "ahash", "base64 0.22.1", - "bitflags 2.5.0", + "bitflags 2.6.0", "brotli", "bytes", "bytestring", @@ -158,18 +158,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e01ed3140b2f8d422c68afa1ed2e85d996ea619c988ac834d255db32138655cb" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "actix-multipart" -version = "0.6.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b960e2aea75f49c8f069108063d12a48d329fc8b60b786dfc7552a9d5918d2d" +checksum = "d5118a26dee7e34e894f7e85aa0ee5080ae4c18bf03c0e30d49a80e418f00a53" dependencies = [ "actix-utils", "actix-web", - "bytes", "derive_more", "futures-core", "futures-util", @@ -178,6 +177,7 @@ dependencies = [ "log", "memchr", "mime", + "rand", "serde", "serde_json", "serde_plain", @@ -200,9 +200,9 @@ dependencies = [ [[package]] name = "actix-rt" -version = "2.9.0" +version = "2.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28f32d40287d3f402ae0028a9d54bef51af15c8769492826a69d28f81893151d" +checksum = "24eda4e2a6e042aa4e55ac438a2ae052d3b5da0ecf83d7411e1a368946925208" dependencies = [ "futures-core", "tokio", @@ -210,9 +210,9 @@ dependencies = [ [[package]] name = "actix-server" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3eb13e7eef0423ea6eab0e59f6c72e7cb46d33691ad56a726b3cd07ddec2c2d4" +checksum = "b02303ce8d4e8be5b855af6cf3c3a08f3eff26880faad82bab679c22d3650cb5" dependencies = [ "actix-rt", "actix-service", @@ -315,7 +315,7 @@ dependencies = [ "actix-router", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -497,9 +497,9 @@ dependencies = [ [[package]] name = "async-compression" -version = "0.4.11" +version = "0.4.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd066d0b4ef8ecb03a55319dc13aa6910616d0f44008a045bb1835af830abff5" +checksum = "fec134f64e2bc57411226dfc4e52dec859ddfc7e711fc5e07b612584f000e4aa" dependencies = [ "flate2", "futures-core", @@ -538,7 +538,7 @@ checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -549,7 +549,7 @@ checksum = "6e0c28dcc82d7c8ead5cb13beb15405b57b8546e93215673ff8ca0349a028107" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -565,12 +565,6 @@ dependencies = [ "quick-xml 0.31.0", ] -[[package]] -name = "atomic" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59bdb34bc650a32731b31bd8f0829cc15d24a708ee31559e0bb34f2bc320cba" - [[package]] name = "atomic-waker" version = "1.1.2" @@ -585,9 +579,9 @@ checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0" [[package]] name = "aws-lc-rs" -version = "1.7.2" +version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "474d7cec9d0a1126fad1b224b767fcbf351c23b0309bb21ec210bcfd379926a5" +checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -598,9 +592,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.17.0" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7505fc3cb7acbf42699a43a79dd9caa4ed9e99861dfbb837c5c0fb5a0a8d2980" +checksum = "2e89b6941c2d1a7045538884d6e760ccfffdf8e1ffc2613d8efa74305e1f3752" dependencies = [ "bindgen", "cc", @@ -624,7 +618,7 @@ dependencies = [ "futures-util", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "itoa", "matchit 0.7.3", "memchr", @@ -633,7 +627,7 @@ dependencies = [ "pin-project-lite", "rustversion", "serde", - "sync_wrapper", + "sync_wrapper 0.1.2", "tower", "tower-layer", "tower-service", @@ -709,12 +703,11 @@ checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b" [[package]] name = "bb8" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df7c2093d15d6a1d33b1f972e1c5ea3177748742b97a5f392aa83a65262c6780" +checksum = "b10cf871f3ff2ce56432fddc2615ac7acc3aa22ca321f8fea800846fbb32f188" dependencies = [ "async-trait", - "futures-channel", "futures-util", "parking_lot 0.12.3", "tokio", @@ -758,7 +751,7 @@ version = "0.69.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a00dc851838a2120612785d195287475a3ac45514741da670b735818822129a0" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cexpr", "clang-sys", "itertools 0.12.1", @@ -771,7 +764,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 2.0.66", + "syn 2.0.72", "which", ] @@ -798,9 +791,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.5.0" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" dependencies = [ "serde", ] @@ -859,9 +852,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.0" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78834c15cb5d5efe3452d58b1e8ba890dd62d21907f867f383358198e56ebca5" +checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" [[package]] name = "byteorder" @@ -900,13 +893,12 @@ dependencies = [ [[package]] name = "cc" -version = "1.0.98" +version = "1.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41c270e7540d725e65ac7f1b212ac8ce349719624d7bcff99f8e2e488e8cf03f" +checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" dependencies = [ "jobserver", "libc", - "once_cell", ] [[package]] @@ -942,7 +934,7 @@ dependencies = [ "num-traits", "serde", "wasm-bindgen", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -978,9 +970,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84b3edb18336f4df585bc9aa31dd99c036dfa5dc5e9a2939a722a188f3a8970d" +checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" dependencies = [ "clap_builder", "clap_derive", @@ -988,9 +980,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.8" +version = "4.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1c09dd5ada6c6c78075d6fd0da3f90d8080651e2d6cc8eb2f1aaa4034ced708" +checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" dependencies = [ "anstream", "anstyle", @@ -1007,7 +999,7 @@ dependencies = [ "heck 0.5.0", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1104,7 +1096,7 @@ dependencies = [ "ron", "serde", "serde_json", - "toml 0.8.14", + "toml 0.8.15", "yaml-rust", ] @@ -1312,12 +1304,12 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83b2eb4d90d12bdda5ed17de686c2acb4c57914f8f921b8da7e112b5a36f3fe1" +checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" dependencies = [ - "darling_core 0.20.9", - "darling_macro 0.20.9", + "darling_core 0.20.10", + "darling_macro 0.20.10", ] [[package]] @@ -1336,16 +1328,16 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "622687fe0bac72a04e5599029151f5796111b90f1baaa9b544d807a5e31cd120" +checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" dependencies = [ "fnv", "ident_case", "proc-macro2", "quote", "strsim 0.11.1", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1361,13 +1353,13 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.9" +version = "0.20.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733cabb43482b1a1b53eee8583c2b9e8684d592215ea83efd305dd31bc2f0178" +checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" dependencies = [ - "darling_core 0.20.9", + "darling_core 0.20.10", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1431,13 +1423,13 @@ dependencies = [ [[package]] name = "der_derive" -version = "0.7.2" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5fe87ce4529967e0ba1dcf8450bab64d97dfd5010a6256187ffe2e43e6f0e049" +checksum = "8034092389675178f570469e6c3b0465d3d30b4505c294a6550db47f3c17ad18" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1469,7 +1461,7 @@ checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1487,10 +1479,10 @@ version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d48cda787f839151732d396ac69e3473923d54312c070ee21e9effcaa8ca0b1d" dependencies = [ - "darling 0.20.9", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1500,20 +1492,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "206868b8242f27cecce124c19fd88157fbd0dd334df2587f36417bafbc85097b" dependencies = [ "derive_builder_core", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "derive_more" -version = "0.99.17" +version = "0.99.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" +checksum = "5f33878137e4dafd7fa914ad4e259e18a4e8e532b9617a2d0150262bf53abfce" dependencies = [ "convert_case", "proc-macro2", "quote", "rustc_version", - "syn 1.0.109", + "syn 2.0.72", ] [[package]] @@ -1531,7 +1523,7 @@ version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ff236accb9a5069572099f0b350a92e9560e8e63a9b8d546162f4a5e03026bb2" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "byteorder", "chrono", "diesel_derives", @@ -1567,7 +1559,7 @@ dependencies = [ "heck 0.4.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1578,7 +1570,7 @@ checksum = "d5adf688c584fe33726ce0e2898f608a2a92578ac94a4a92fcecf73214fe0716" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1590,7 +1582,7 @@ dependencies = [ "diesel_table_macro_syntax", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1620,7 +1612,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc5557efc453706fed5e4fa85006fe9817c224c3f480a34c7e5959fd700921c5" dependencies = [ - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1700,9 +1692,9 @@ checksum = "0d6ef0072f8a535281e4876be788938b528e9a1d43900b82c2569af7da799125" [[package]] name = "either" -version = "1.12.0" +version = "1.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dca9240753cf90908d7e4aac30f630662b02aebaa1b58a3cadabdb23385b58b" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" [[package]] name = "elementtree" @@ -1725,9 +1717,9 @@ dependencies = [ [[package]] name = "email_address" -version = "0.2.4" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2153bd83ebc09db15bcbdc3e2194d901804952e3dc96967e1cd3b0c5c32d112" +checksum = "46b7a0ac6570e31bfe2c6cf575a576a55af9893d1a6b30b4444e6e90b216bb84" [[package]] name = "encoding_rs" @@ -1761,7 +1753,7 @@ checksum = "f282cfdfe92516eb26c2af8589c274c7c17681f5ecc03c18255fe741c6aa64eb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -1877,9 +1869,9 @@ dependencies = [ [[package]] name = "flagset" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb3aa5e95cf9aabc17f060cfa0ced7b83f042390760ca53bf09df9968acaa1" +checksum = "b3ea1ec5f8307826a5b71094dd91fc04d4ae75d5709b20ad351c7fb4815c86ec" [[package]] name = "flate2" @@ -2009,7 +2001,7 @@ checksum = "87750cf4b7a4c0625b1529e4c543c2182106e4dedc60a2a6455e00d212c489ac" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2271,7 +2263,7 @@ dependencies = [ "markup5ever 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2309,9 +2301,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.0" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643" +checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" dependencies = [ "bytes", "http 1.1.0", @@ -2319,14 +2311,14 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0475f8b2ac86659c21b64320d5d653f9efe42acd2a4e560073ec61a155a34f1d" +checksum = "793429d76616a256bcb62c2a2ec2bed781c8307e797e2598c50010f2bee2544f" dependencies = [ "bytes", - "futures-core", + "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "pin-project-lite", ] @@ -2358,9 +2350,9 @@ dependencies = [ [[package]] name = "httparse" -version = "1.8.0" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" +checksum = "0fcc0b4a115bf80b728eb8ea024ad5bd707b615bfed49e0665b6e0f86fd082d9" [[package]] name = "httpdate" @@ -2376,9 +2368,9 @@ checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" -version = "0.14.29" +version = "0.14.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33" +checksum = "a152ddd61dfaec7273fe8419ab357f33aee0d914c5f4efbf0d96fa749eea5ec9" dependencies = [ "bytes", "futures-channel", @@ -2400,16 +2392,16 @@ dependencies = [ [[package]] name = "hyper" -version = "1.3.1" +version = "1.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d" +checksum = "50dfd22e0e76d0f662d429a5f80fcaf3855009297eab6a0a9f8543834744ba05" dependencies = [ "bytes", "futures-channel", "futures-util", "h2 0.4.5", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "httparse", "httpdate", "itoa", @@ -2427,7 +2419,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590" dependencies = [ "futures-util", "http 0.2.12", - "hyper 0.14.29", + "hyper 0.14.30", "rustls 0.21.12", "tokio", "tokio-rustls 0.24.1", @@ -2435,19 +2427,20 @@ dependencies = [ [[package]] name = "hyper-rustls" -version = "0.26.0" +version = "0.27.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0bea761b46ae2b24eb4aef630d8d1c398157b6fc29e6350ecf090a0b70c952c" +checksum = "5ee4be2c948921a1a5320b629c4193916ed787a7f7f293fd3f7f5a6c9de74155" dependencies = [ "futures-util", "http 1.1.0", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", - "rustls 0.22.4", + "rustls 0.23.11", "rustls-pki-types", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tower-service", + "webpki-roots 0.26.3", ] [[package]] @@ -2456,7 +2449,7 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" dependencies = [ - "hyper 0.14.29", + "hyper 0.14.30", "pin-project-lite", "tokio", "tokio-io-timeout", @@ -2469,7 +2462,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" dependencies = [ "bytes", - "hyper 0.14.29", + "hyper 0.14.30", "native-tls", "tokio", "tokio-native-tls", @@ -2477,16 +2470,16 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b875924a60b96e5d7b9ae7b066540b1dd1cbd90d1828f54c92e02a283351c56" +checksum = "3ab92f4f49ee4fb4f997c784b7a2e0fa70050211e0b6a287f898c3c9785ca956" dependencies = [ "bytes", "futures-channel", "futures-util", "http 1.1.0", - "http-body 1.0.0", - "hyper 1.3.1", + "http-body 1.0.1", + "hyper 1.4.1", "pin-project-lite", "socket2", "tokio", @@ -2512,7 +2505,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8215279f83f9b829403812f845aa2d0dd5966332aa2fd0334a375256f3dd0322" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -2735,11 +2728,11 @@ checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" [[package]] name = "lazy_static" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" dependencies = [ - "spin 0.5.2", + "spin", ] [[package]] @@ -2869,7 +2862,7 @@ dependencies = [ "serde_with", "serial_test", "stringreader", - "strum_macros", + "strum", "tokio", "tracing", "url", @@ -2915,13 +2908,12 @@ dependencies = [ "once_cell", "pretty_assertions", "regex", - "rustls 0.23.10", + "rustls 0.23.11", "serde", "serde_json", "serde_with", "serial_test", "strum", - "strum_macros", "tokio", "tokio-postgres", "tokio-postgres-rustls", @@ -2969,7 +2961,6 @@ dependencies = [ "serde_with", "serial_test", "strum", - "strum_macros", "tokio", "ts-rs", "url", @@ -3075,7 +3066,7 @@ dependencies = [ "reqwest 0.11.27", "reqwest-middleware 0.2.5", "reqwest-tracing 0.4.8", - "rustls 0.23.10", + "rustls 0.23.11", "serde_json", "serial_test", "tokio", @@ -3116,7 +3107,6 @@ dependencies = [ "serde_json", "smart-default", "strum", - "strum_macros", "tokio", "tracing", "tracing-error", @@ -3146,13 +3136,13 @@ dependencies = [ "nom", "percent-encoding", "quoted_printable", - "rustls 0.23.10", + "rustls 0.23.11", "rustls-pemfile 2.1.2", "socket2", "tokio", "tokio-rustls 0.26.0", "url", - "webpki-roots 0.26.2", + "webpki-roots 0.26.3", ] [[package]] @@ -3163,12 +3153,12 @@ checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "libloading" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c2a198fb6b0eada2a8df47933734e6d35d350665a33a3593d7164fa52c75c19" +checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -3177,12 +3167,6 @@ version = "0.2.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ec2a862134d2a7d32d7983ddcdd1c4923530833c9f2ea1a44fc5fa473989058" -[[package]] -name = "line-wrap" -version = "0.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd1bc4d24ad230d21fb898d1116b1801d7adfc449d42026475862ab48b11e70e" - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -3233,9 +3217,9 @@ dependencies = [ [[package]] name = "lodepng" -version = "3.10.1" +version = "3.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a42d298694b14401847de29abd44adf278b42e989e516deac7b72018400002d8" +checksum = "72decff904ebe3e39c88b0488985f24e9796bb4dc5bcf65beebaa5d3b7073ff4" dependencies = [ "crc32fast", "fallible_collections", @@ -3246,9 +3230,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.21" +version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" +checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" [[package]] name = "mac" @@ -3258,9 +3242,9 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" [[package]] name = "markdown-it" -version = "0.6.0" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "181d1b4704b0a2fc6027d3f758a7eedb975dcbaab86e6794901b8cfc52af94d5" +checksum = "f99c010929c8217b2dc0940954267a2e15a15f17cb309cd1f299e21933f84fac" dependencies = [ "argparse", "const_format", @@ -3348,9 +3332,9 @@ checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "matchit" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "540f1c43aed89909c0cc0cc604e3bb2f7e7a341a3728a9e6cfe760e733cd11ed" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" [[package]] name = "md-5" @@ -3375,9 +3359,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.7.2" +version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d" +checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" [[package]] name = "metrics" @@ -3391,13 +3375,13 @@ dependencies = [ [[package]] name = "metrics-exporter-prometheus" -version = "0.15.0" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26eb45aff37b45cff885538e1dcbd6c2b462c04fe84ce0155ea469f325672c98" +checksum = "b4f0c8427b39666bf970460908b213ec09b3b350f20c0c2eabcbba51704a08e6" dependencies = [ "base64 0.22.1", "http-body-util", - "hyper 1.3.1", + "hyper 1.4.1", "hyper-util", "indexmap 2.2.6", "ipnet", @@ -3453,9 +3437,9 @@ checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" [[package]] name = "mime_guess" -version = "2.0.4" +version = "2.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e" dependencies = [ "mime", "unicase", @@ -3469,9 +3453,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87dfd01fe195c66b572b37921ad8803d010623c0aca821bea2302239d155cdae" +checksum = "b8a240ddb74feaf34a79a7add65a741f3167852fba007066dcac1ca548d89c08" dependencies = [ "adler", "simd-adler32", @@ -3519,7 +3503,7 @@ dependencies = [ "cfg-if", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3609,9 +3593,9 @@ dependencies = [ [[package]] name = "num-bigint" -version = "0.4.5" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c165a9ab64cf766f73521c0dd2cfdff64f488b8f0b3e621face3462d3db536d7" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" dependencies = [ "num-integer", "num-traits", @@ -3697,11 +3681,11 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" [[package]] name = "openssl" -version = "0.10.64" +version = "0.10.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a0481286a310808298130d22dd1fef0fa571e05a8f44ec801801e84b216b1f" +checksum = "9529f4786b70a3e8c61e11179af17ab6188ad8d0ded78c5529441ed39d4bd9c1" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "cfg-if", "foreign-types", "libc", @@ -3718,7 +3702,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -3729,9 +3713,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.102" +version = "0.9.103" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c597637d56fbc83893a35eb0dd04b2b8e7a50c91e64e9493e398b5df4fb45fa2" +checksum = "7f9e8deee91df40a943c71b917e5874b951d32a802526c85721ce3b776c929d6" dependencies = [ "cc", "libc", @@ -3903,9 +3887,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.0" +version = "4.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a76df7075c7d4d01fdcb46c912dd17fba5b60c78ea480b475f2b6ab6f666584e" +checksum = "19ff2cf528c6c03d9ed653d6c4ce1dc0582dc4af309790ad92f07c1cd551b0be" dependencies = [ "num-traits", ] @@ -3971,9 +3955,9 @@ checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.1", + "redox_syscall 0.5.3", "smallvec", - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -4121,10 +4105,10 @@ dependencies = [ "opentelemetry_sdk 0.23.0", "pin-project-lite", "refinery", - "reqwest 0.12.4", - "reqwest-middleware 0.3.1", - "reqwest-tracing 0.5.0", - "rustls 0.23.10", + "reqwest 0.12.5", + "reqwest-middleware 0.3.2", + "reqwest-tracing 0.5.2", + "rustls 0.23.11", "rustls-channel-resolver", "rustls-pemfile 2.1.2", "rusty-s3", @@ -4142,7 +4126,7 @@ dependencies = [ "tokio-postgres", "tokio-postgres-generic-rustls", "tokio-util", - "toml 0.8.14", + "toml 0.8.15", "tracing", "tracing-actix-web", "tracing-error", @@ -4151,7 +4135,7 @@ dependencies = [ "tracing-subscriber", "url", "uuid", - "webpki-roots 0.26.2", + "webpki-roots 0.26.3", ] [[package]] @@ -4171,7 +4155,7 @@ checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4215,14 +4199,13 @@ checksum = "d231b230927b5e4ad203db57bbcbee2802f6bce620b1e4a9024a07d94e2907ec" [[package]] name = "plist" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" +checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "indexmap 2.2.6", - "line-wrap", - "quick-xml 0.31.0", + "quick-xml 0.32.0", "serde", "time", ] @@ -4242,15 +4225,15 @@ dependencies = [ [[package]] name = "portable-atomic" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7170ef9988bc169ba16dd36a7fa041e5c4cbeb6a35b76d4c03daded371eae7c0" +checksum = "da544ee218f0d287a911e9c99a39a8c9bc8fcad3cb8db5959940044ecfc67265" [[package]] name = "postgres" -version = "0.19.7" +version = "0.19.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7915b33ed60abc46040cbcaa25ffa1c7ec240668e0477c4f3070786f5916d451" +checksum = "6c9ec84ab55b0f9e418675de50052d494ba893fd28c65769a6e68fcdacbee2b8" dependencies = [ "bytes", "fallible-iterator", @@ -4262,11 +4245,11 @@ dependencies = [ [[package]] name = "postgres-protocol" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b6c5ef183cd3ab4ba005f1ca64c21e8bd97ce4699cfea9e8d9a2c4958ca520" +checksum = "acda0ebdebc28befa84bee35e651e4c5f09073d668c7aed4cf7e23c3cda84b23" dependencies = [ - "base64 0.21.7", + "base64 0.22.1", "byteorder", "bytes", "fallible-iterator", @@ -4280,9 +4263,9 @@ dependencies = [ [[package]] name = "postgres-types" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d2234cdee9408b523530a9b6d2d6b373d1db34f6a8e51dc03ded1828d7fb67c" +checksum = "02048d9e032fb3cc3413bbf7b83a15d84a5d419778e2628751896d856498eee9" dependencies = [ "bytes", "fallible-iterator", @@ -4363,14 +4346,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" dependencies = [ "proc-macro2", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "proc-macro2" -version = "1.0.85" +version = "1.0.86" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22244ce15aa966053a896d1accb3a6e68469b97c7f33f284b99f0d576879fc23" +checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77" dependencies = [ "unicode-ident", ] @@ -4381,7 +4364,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "731e0d9356b0c25f16f33b5be79b1c57b562f141ebfcdb0ad8ac2c13a24293b4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "hex", "lazy_static", "procfs-core", @@ -4394,7 +4377,7 @@ version = "0.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2d3554923a69f4ce04c4a754260c338f505ce22642d3830e049a399fc2059a29" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "hex", ] @@ -4458,7 +4441,7 @@ dependencies = [ "itertools 0.12.1", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4520,6 +4503,61 @@ dependencies = [ "memchr", ] +[[package]] +name = "quick-xml" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d3a6e5838b60e0e8fa7a43f22ade549a37d61f8bdbe636d0d7816191de969c2" +dependencies = [ + "memchr", +] + +[[package]] +name = "quinn" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4ceeeeabace7857413798eb1ffa1e9c905a9946a57d81fb69b4b71c4d8eb3ad" +dependencies = [ + "bytes", + "pin-project-lite", + "quinn-proto", + "quinn-udp", + "rustc-hash", + "rustls 0.23.11", + "thiserror", + "tokio", + "tracing", +] + +[[package]] +name = "quinn-proto" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddf517c03a109db8100448a4be38d498df8a210a99fe0e1b9eaf39e78c640efe" +dependencies = [ + "bytes", + "rand", + "ring", + "rustc-hash", + "rustls 0.23.11", + "slab", + "thiserror", + "tinyvec", + "tracing", +] + +[[package]] +name = "quinn-udp" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25a78e6f726d84fcf960409f509ae354a32648f090c8d32a2ea8b1a1bc3bab14" +dependencies = [ + "libc", + "once_cell", + "socket2", + "windows-sys 0.52.0", +] + [[package]] name = "quote" version = "1.0.36" @@ -4531,9 +4569,9 @@ dependencies = [ [[package]] name = "quoted_printable" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79ec282e887b434b68c18fe5c121d38e72a5cf35119b59e54ec5b992ea9c8eb0" +checksum = "640c9bd8497b02465aeef5375144c26062e0dcd5939dfcbb0f5db76cb8c17c73" [[package]] name = "rand" @@ -4567,11 +4605,11 @@ dependencies = [ [[package]] name = "raw-cpuid" -version = "11.0.2" +version = "11.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e29830cbb1290e404f24c73af91c5d8d631ce7e128691e9477556b540cd01ecd" +checksum = "cb9ee317cfe3fbd54b36a511efc1edd42e216903c9cd575e686dd68a2ba90d8d" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4582,7 +4620,7 @@ checksum = "a25d631e41bfb5fdcde1d4e2215f62f7f0afa3ff11e26563765bd6ea1d229aeb" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4605,11 +4643,11 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.1" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e" +checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", ] [[package]] @@ -4639,7 +4677,7 @@ dependencies = [ "time", "tokio", "tokio-postgres", - "toml 0.8.14", + "toml 0.8.15", "url", "walkdir", ] @@ -4655,7 +4693,7 @@ dependencies = [ "quote", "refinery-core", "regex", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -4666,8 +4704,8 @@ checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" dependencies = [ "aho-corasick", "memchr", - "regex-automata 0.4.6", - "regex-syntax 0.8.3", + "regex-automata 0.4.7", + "regex-syntax 0.8.4", ] [[package]] @@ -4681,20 +4719,20 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.4.6" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea" +checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", ] [[package]] name = "regex-lite" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30b661b2f27137bdbc16f00eda72866a92bb28af1753ffbd56744fb6e2e9cd8e" +checksum = "53a49587ad06b26609c52e423de037e7f57f20d53535d66e08c695f347df952a" [[package]] name = "regex-syntax" @@ -4704,9 +4742,9 @@ checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" [[package]] name = "regex-syntax" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56" +checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b" [[package]] name = "reqwest" @@ -4723,7 +4761,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-rustls 0.24.2", "hyper-tls", "ipnet", @@ -4740,7 +4778,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 0.1.2", "system-configuration", "tokio", "tokio-native-tls", @@ -4758,19 +4796,19 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.12.4" +version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "566cafdd92868e0939d3fb961bd0dc25fcfaaed179291093b3d43e6b3150ea10" +checksum = "c7d6d2a27d57148378eb5e111173f4276ad26340ecc5c49a4a2152167a2d6a37" dependencies = [ "base64 0.22.1", "bytes", "futures-core", "futures-util", "http 1.1.0", - "http-body 1.0.0", + "http-body 1.0.1", "http-body-util", - "hyper 1.3.1", - "hyper-rustls 0.26.0", + "hyper 1.4.1", + "hyper-rustls 0.27.2", "hyper-util", "ipnet", "js-sys", @@ -4779,15 +4817,16 @@ dependencies = [ "once_cell", "percent-encoding", "pin-project-lite", - "rustls 0.22.4", + "quinn", + "rustls 0.23.11", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", "serde_json", "serde_urlencoded", - "sync_wrapper", + "sync_wrapper 1.0.1", "tokio", - "tokio-rustls 0.25.0", + "tokio-rustls 0.26.0", "tokio-util", "tower-service", "url", @@ -4795,7 +4834,7 @@ dependencies = [ "wasm-bindgen-futures", "wasm-streams", "web-sys", - "webpki-roots 0.26.2", + "webpki-roots 0.26.3", "winreg 0.52.0", ] @@ -4816,14 +4855,14 @@ dependencies = [ [[package]] name = "reqwest-middleware" -version = "0.3.1" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a45d100244a467870f6cb763c4484d010a6bed6bd610b3676e3825d93fb4cfbd" +checksum = "39346a33ddfe6be00cbc17a34ce996818b97b230b87229f10114693becca1268" dependencies = [ "anyhow", "async-trait", "http 1.1.0", - "reqwest 0.12.4", + "reqwest 0.12.5", "serde", "thiserror", "tower-service", @@ -4849,17 +4888,17 @@ dependencies = [ [[package]] name = "reqwest-tracing" -version = "0.5.0" +version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b253954a1979e02eabccd7e9c3d61d8f86576108baa160775e7f160bb4e800a3" +checksum = "4e45dcad05dc210fdb0278d62a679eb768730af808f8cb552f810da89bdbe76d" dependencies = [ "anyhow", "async-trait", "getrandom", "http 1.1.0", - "matchit 0.8.2", - "reqwest 0.12.4", - "reqwest-middleware 0.3.1", + "matchit 0.8.4", + "reqwest 0.12.5", + "reqwest-middleware 0.3.2", "tracing", ] @@ -4871,9 +4910,9 @@ checksum = "4389f1d5789befaf6029ebd9f7dac4af7f7e3d61b69d4f30e2ac02b57e7712b0" [[package]] name = "rgb" -version = "0.8.37" +version = "0.8.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05aaa8004b64fd573fc9d002f4e632d51ad4f026c2b5ba95fcb6c2f32c2c47d8" +checksum = "ade4539f42266ded9e755c605bdddf546242b2c961b03b06a7375260788a0523" dependencies = [ "bytemuck", ] @@ -4888,7 +4927,7 @@ dependencies = [ "cfg-if", "getrandom", "libc", - "spin 0.9.8", + "spin", "untrusted 0.9.0", "windows-sys 0.52.0", ] @@ -4900,7 +4939,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ "base64 0.21.7", - "bitflags 2.5.0", + "bitflags 2.6.0", "serde", "serde_derive", ] @@ -4984,7 +5023,7 @@ version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "errno", "libc", "linux-raw-sys", @@ -5005,30 +5044,16 @@ dependencies = [ [[package]] name = "rustls" -version = "0.22.4" +version = "0.23.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf4ef73721ac7bcd79b2b315da7779d8fc09718c6b3d2d1b2d94850eb8c18432" -dependencies = [ - "log", - "ring", - "rustls-pki-types", - "rustls-webpki 0.102.4", - "subtle", - "zeroize", -] - -[[package]] -name = "rustls" -version = "0.23.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05cff451f60db80f490f3c182b77c35260baace73209e9cdbbe526bfe3a4d402" +checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" dependencies = [ "aws-lc-rs", "log", "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.102.4", + "rustls-webpki 0.102.6", "subtle", "zeroize", ] @@ -5040,7 +5065,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fede2a247359da6b4998f7723ec6468c2d6a577a5d8c17e54f21806426ad2290" dependencies = [ "nanorand", - "rustls 0.23.10", + "rustls 0.23.11", ] [[package]] @@ -5080,9 +5105,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.102.4" +version = "0.102.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff448f7e92e913c4b7d4c6d8e4540a1724b319b4152b8aef6d4cf8339712b33e" +checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" dependencies = [ "aws-lc-rs", "ring", @@ -5132,9 +5157,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.1" +version = "2.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76ad2bbb0ae5100a07b7a6f2ed7ab5fd0045551a4c507989b7a620046ea3efdc" +checksum = "a4465c22496331e20eb047ff46e7366455bc01c0c02015c4a376de0b2cd3a1af" dependencies = [ "sdd", ] @@ -5176,17 +5201,17 @@ dependencies = [ [[package]] name = "sdd" -version = "0.2.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b84345e4c9bd703274a082fb80caaa99b7612be48dfaa1dd9266577ec412309d" +checksum = "85f05a494052771fc5bd0619742363b5e24e5ad72ab3111ec2e27925b8edc5f3" [[package]] name = "security-framework" -version = "2.11.0" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c627723fd09706bacdb5cf41499e95098555af3c3c29d014dc3c458ef6be11c0" +checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02" dependencies = [ - "bitflags 2.5.0", + "bitflags 2.6.0", "core-foundation", "core-foundation-sys", "libc", @@ -5246,7 +5271,7 @@ checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5293,9 +5318,9 @@ dependencies = [ [[package]] name = "serde_with" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad483d2ab0149d5a5ebcd9972a3852711e0153d863bf5a5d0391d28883c4a20" +checksum = "69cecfa94848272156ea67b2b1a53f20fc7bc638c4a46d2f8abde08f05f4b857" dependencies = [ "base64 0.22.1", "chrono", @@ -5311,14 +5336,14 @@ dependencies = [ [[package]] name = "serde_with_macros" -version = "3.8.1" +version = "3.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65569b702f41443e8bc8bbb1c5779bd0450bbe723b56198980e80ec45780bce2" +checksum = "a8fee4991ef4f274617a51ad4af30519438dacb2f56ac773b08a1922ff743350" dependencies = [ - "darling 0.20.9", + "darling 0.20.10", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5343,7 +5368,7 @@ checksum = "82fe9db325bcef1fbcde82e078a5cc4efdf787e96b3b9cf45b50b529f2083d67" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5487,7 +5512,7 @@ checksum = "0eb01866308440fc64d6c44d9e86c5cc17adfe33c4d6eed55da9145044d0ffc1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5500,12 +5525,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "spin" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" - [[package]] name = "spin" version = "0.9.8" @@ -5608,9 +5627,12 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "strum" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d8cec3501a5194c432b2b7976db6b7d10ec95c253208b45f83f7136aa985e29" +checksum = "8fec0f0aef304996cf250b31b5a10dee7980c85da9d759361292b8bca5a18f06" +dependencies = [ + "strum_macros", +] [[package]] name = "strum_macros" @@ -5622,14 +5644,14 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "subtle" -version = "2.5.0" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81cdd64d312baedb58e21336b31bc043b77e01cc99033ce76ef539f78e965ebc" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" @@ -5644,9 +5666,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.66" +version = "2.0.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c42f3f41a2de00b01c0aaad383c5a45241efc8b2d1eda5661812fda5f3cdcff5" +checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" dependencies = [ "proc-macro2", "quote", @@ -5659,6 +5681,12 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "sync_wrapper" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7065abeca94b6a8a577f9bd45aa0867a2238b74e8eb67cf10d492bc39351394" + [[package]] name = "syntect" version = "5.2.0" @@ -5672,7 +5700,7 @@ dependencies = [ "fnv", "once_cell", "plist", - "regex-syntax 0.8.3", + "regex-syntax 0.8.4", "serde", "serde_derive", "serde_json", @@ -5773,27 +5801,27 @@ checksum = "78ea17a2dc368aeca6f554343ced1b1e31f76d63683fa8016e5844bd7a5144a1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "thiserror" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb" +checksum = "c0342370b38b6a11b6cc11d6a805569958d54cfa061a29969c3b5ce2ea405724" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.62" +version = "1.0.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c" +checksum = "a4558b58466b9ad7ca0f102865eccc95938dca1a74a856f2b57b6629050da261" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5845,9 +5873,9 @@ checksum = "9ab95735ea2c8fd51154d01e39cf13912a78071c2d89abc49a7ef102a7dd725a" [[package]] name = "tinyvec" -version = "1.6.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87cc5ceb3875bb20c2890005a4e226a4651264a5c75edb2421b52861a0a0cb50" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" dependencies = [ "tinyvec_macros", ] @@ -5876,14 +5904,14 @@ checksum = "8d9ef545650e79f30233c0003bcc2504d7efac6dad25fca40744de773fe2049c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "tokio" -version = "1.38.0" +version = "1.38.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba4f4a02a7a80d6f274636f0aa95c7e383b912d41fe721a31f29e29698585a4a" +checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" dependencies = [ "backtrace", "bytes", @@ -5917,7 +5945,7 @@ checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -5932,9 +5960,9 @@ dependencies = [ [[package]] name = "tokio-postgres" -version = "0.7.10" +version = "0.7.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d340244b32d920260ae7448cb72b6e238bddc3d4f7603394e7dd46ed8e48f5b8" +checksum = "03adcf0147e203b6032c0b2d30be1415ba03bc348901f3ff1cc0df6a733e60c3" dependencies = [ "async-trait", "byteorder", @@ -5963,7 +5991,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8e98c31c29b2666fb28720739e11476166be4ead1610a37dcd7414bb124413a" dependencies = [ "aws-lc-rs", - "rustls 0.23.10", + "rustls 0.23.11", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -5977,7 +6005,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.10", + "rustls 0.23.11", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -5994,24 +6022,13 @@ dependencies = [ "tokio", ] -[[package]] -name = "tokio-rustls" -version = "0.25.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "775e0c0f0adb3a2f22a00c4745d728b479985fc15ee7ca6a2608388c5569860f" -dependencies = [ - "rustls 0.22.4", - "rustls-pki-types", - "tokio", -] - [[package]] name = "tokio-rustls" version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.10", + "rustls 0.23.11", "rustls-pki-types", "tokio", ] @@ -6054,14 +6071,14 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.14" +version = "0.8.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f49eb2ab21d2f26bd6db7bf383edc527a7ebaee412d17af4d40fdccd442f335" +checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.14", + "toml_edit 0.22.16", ] [[package]] @@ -6088,15 +6105,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.14" +version = "0.22.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f21c7aaf97f1bd9ca9d4f9e73b0a6c74bd5afef56f2bc931943a6e1c37e04e38" +checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.13", + "winnow 0.6.14", ] [[package]] @@ -6115,7 +6132,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -6145,7 +6162,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -6172,7 +6189,7 @@ dependencies = [ "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", - "hyper 0.14.29", + "hyper 0.14.30", "hyper-timeout", "percent-encoding", "pin-project", @@ -6268,7 +6285,7 @@ checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -6417,7 +6434,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04659ddb06c87d233c566112c1c9c5b9e98256d9af50ec3bc9c8327f873a7568" dependencies = [ "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -6452,7 +6469,7 @@ dependencies = [ "Inflector", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "termcolor", ] @@ -6473,7 +6490,7 @@ checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -6580,17 +6597,16 @@ checksum = "86bd8d4e895da8537e5315b8254664e6b769c4ff3db18321b297a1e7004392e3" [[package]] name = "utf8parse" -version = "0.2.1" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.8.0" +version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0" +checksum = "81dfa00651efa65069b0b6b651f4aaa31ba9e3c3ce0137aaad053604ee7e0314" dependencies = [ - "atomic", "getrandom", "serde", ] @@ -6665,7 +6681,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-shared", ] @@ -6699,7 +6715,7 @@ checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6779,9 +6795,9 @@ checksum = "5f20c57d8d7db6d3b86154206ae5d8fba62dd39573114de97c2cb0578251f8e1" [[package]] name = "webpki-roots" -version = "0.26.2" +version = "0.26.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c452ad30530b54a4d8e71952716a212b08efd0f3562baa66c29a618b07da7c3" +checksum = "bd7c23921eeb1713a4e851530e9b9756e4fb0e89978582942612524cf09f01cd" dependencies = [ "rustls-pki-types", ] @@ -6846,7 +6862,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6864,7 +6880,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ - "windows-targets 0.52.5", + "windows-targets 0.52.6", ] [[package]] @@ -6884,18 +6900,18 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows_aarch64_gnullvm 0.52.5", - "windows_aarch64_msvc 0.52.5", - "windows_i686_gnu 0.52.5", + "windows_aarch64_gnullvm 0.52.6", + "windows_aarch64_msvc 0.52.6", + "windows_i686_gnu 0.52.6", "windows_i686_gnullvm", - "windows_i686_msvc 0.52.5", - "windows_x86_64_gnu 0.52.5", - "windows_x86_64_gnullvm 0.52.5", - "windows_x86_64_msvc 0.52.5", + "windows_i686_msvc 0.52.6", + "windows_x86_64_gnu 0.52.6", + "windows_x86_64_gnullvm 0.52.6", + "windows_x86_64_msvc 0.52.6", ] [[package]] @@ -6906,9 +6922,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" [[package]] name = "windows_aarch64_msvc" @@ -6918,9 +6934,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" [[package]] name = "windows_i686_gnu" @@ -6930,15 +6946,15 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" [[package]] name = "windows_i686_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" [[package]] name = "windows_i686_msvc" @@ -6948,9 +6964,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" [[package]] name = "windows_x86_64_gnu" @@ -6960,9 +6976,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" [[package]] name = "windows_x86_64_gnullvm" @@ -6972,9 +6988,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" [[package]] name = "windows_x86_64_msvc" @@ -6984,9 +7000,9 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" -version = "0.52.5" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" [[package]] name = "winnow" @@ -6999,9 +7015,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.13" +version = "0.6.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59b5e5f6c299a3c7890b876a2a587f3115162487e704907d9b6cd29473052ba1" +checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" dependencies = [ "memchr", ] @@ -7102,22 +7118,22 @@ checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" [[package]] name = "zerocopy" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae87e3fcd617500e5d106f0380cf7b77f3c6092aae37191433159dda23cfb087" +checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.7.34" +version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "15e934569e47891f7d9411f1a451d947a60e000ab3bd24fbb970f000387d1b3b" +checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] @@ -7137,32 +7153,32 @@ checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" dependencies = [ "proc-macro2", "quote", - "syn 2.0.66", + "syn 2.0.72", ] [[package]] name = "zstd" -version = "0.13.1" +version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2d789b1514203a1120ad2429eae43a7bd32b90976a7bb8a05f7ec02fa88cc23a" +checksum = "fcf2b778a664581e31e389454a7072dab1647606d44f7feea22cd5abb9c9f3f9" dependencies = [ "zstd-safe", ] [[package]] name = "zstd-safe" -version = "7.1.0" +version = "7.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cd99b45c6bc03a018c8b8a86025678c87e55526064e38f9df301989dce7ec0a" +checksum = "fa556e971e7b568dc775c136fc9de8c779b1c2fc3a63defaafadffdbd3181afa" dependencies = [ "zstd-sys", ] [[package]] name = "zstd-sys" -version = "2.0.10+zstd.1.5.6" +version = "2.0.12+zstd.1.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c253a4914af5bafc8fa8c86ee400827e83cf6ec01195ec1f1ed8441bf00d65aa" +checksum = "0a4e40c320c3cb459d9a9ff6de98cff88f4751ee9275d140e2be94a2b74e4c13" dependencies = [ "cc", "pkg-config", diff --git a/Cargo.toml b/Cargo.toml index ca0598f82..96c4e2800 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -149,8 +149,7 @@ regex = "1.10.4" once_cell = "1.19.0" diesel-derive-newtype = "2.1.2" diesel-derive-enum = { version = "2.1.0", features = ["postgres"] } -strum = "0.26.2" -strum_macros = "0.26.4" +strum = { version = "0.26.3", features = ["derive"] } itertools = "0.13.0" futures = "0.3.30" http = "0.2.12" diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index a9c6f657a..8f245d076 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -31,7 +31,7 @@ serde = { workspace = true } actix-web = { workspace = true } tokio = { workspace = true } tracing = { workspace = true } -strum_macros = { workspace = true } +strum = { workspace = true } url = { workspace = true } http = { workspace = true } futures = { workspace = true } diff --git a/crates/apub/src/protocol/activities/community/lock_page.rs b/crates/apub/src/protocol/activities/community/lock_page.rs index c60b86cf8..a08b3c5a2 100644 --- a/crates/apub/src/protocol/activities/community/lock_page.rs +++ b/crates/apub/src/protocol/activities/community/lock_page.rs @@ -13,10 +13,10 @@ use lemmy_api_common::context::LemmyContext; use lemmy_db_schema::{source::community::Community, traits::Crud}; use lemmy_utils::{error::LemmyResult, LemmyErrorType}; use serde::{Deserialize, Serialize}; -use strum_macros::Display; +use strum::Display; use url::Url; -#[derive(Clone, Debug, Deserialize, Serialize, Display)] +#[derive(Clone, Debug, Display, Deserialize, Serialize)] pub enum LockType { Lock, } diff --git a/crates/apub/src/protocol/activities/mod.rs b/crates/apub/src/protocol/activities/mod.rs index ce0808ee9..d1da73a16 100644 --- a/crates/apub/src/protocol/activities/mod.rs +++ b/crates/apub/src/protocol/activities/mod.rs @@ -1,5 +1,5 @@ use serde::{Deserialize, Serialize}; -use strum_macros::Display; +use strum::Display; pub mod block; pub mod community; diff --git a/crates/apub/src/protocol/activities/voting/vote.rs b/crates/apub/src/protocol/activities/voting/vote.rs index b632333c7..9fae264a5 100644 --- a/crates/apub/src/protocol/activities/voting/vote.rs +++ b/crates/apub/src/protocol/activities/voting/vote.rs @@ -8,7 +8,7 @@ use activitypub_federation::{config::Data, fetch::object_id::ObjectId}; use lemmy_api_common::context::LemmyContext; use lemmy_utils::error::{LemmyError, LemmyErrorType, LemmyResult}; use serde::{Deserialize, Serialize}; -use strum_macros::Display; +use strum::Display; use url::Url; #[derive(Clone, Debug, Deserialize, Serialize)] diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index dc924fa91..bf7a8c9b2 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -46,7 +46,6 @@ serde = { workspace = true } serde_with = { workspace = true } url = { workspace = true } strum = { workspace = true } -strum_macros = { workspace = true } serde_json = { workspace = true, optional = true } activitypub_federation = { workspace = true, optional = true } lemmy_utils = { workspace = true, optional = true } diff --git a/crates/db_schema/src/lib.rs b/crates/db_schema/src/lib.rs index 431243221..c29ec6443 100644 --- a/crates/db_schema/src/lib.rs +++ b/crates/db_schema/src/lib.rs @@ -48,7 +48,7 @@ pub mod utils; mod schema_setup; use serde::{Deserialize, Serialize}; -use strum_macros::{Display, EnumString}; +use strum::{Display, EnumString}; #[cfg(feature = "full")] use ts_rs::TS; diff --git a/crates/db_views_actor/Cargo.toml b/crates/db_views_actor/Cargo.toml index d9e6a3352..af139b8b2 100644 --- a/crates/db_views_actor/Cargo.toml +++ b/crates/db_views_actor/Cargo.toml @@ -33,7 +33,6 @@ serde_with = { workspace = true } ts-rs = { workspace = true, optional = true } chrono.workspace = true strum = { workspace = true } -strum_macros = { workspace = true } [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/db_views_actor/src/person_view.rs b/crates/db_views_actor/src/person_view.rs index 26e4ee680..7a2edfb44 100644 --- a/crates/db_views_actor/src/person_view.rs +++ b/crates/db_views_actor/src/person_view.rs @@ -27,7 +27,7 @@ use lemmy_db_schema::{ SortType, }; use serde::{Deserialize, Serialize}; -use strum_macros::{Display, EnumString}; +use strum::{Display, EnumString}; enum ListMode { Admins, diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index b9cf9ae21..1b71b577a 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -64,7 +64,6 @@ actix-web = { workspace = true, optional = true } anyhow = { workspace = true, optional = true } reqwest-middleware = { workspace = true, optional = true } strum = { workspace = true } -strum_macros = { workspace = true } futures = { workspace = true, optional = true } diesel = { workspace = true, features = ["chrono"], optional = true } http = { workspace = true, optional = true } diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index b848916b2..896539057 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -1,7 +1,7 @@ use cfg_if::cfg_if; use serde::{Deserialize, Serialize}; use std::fmt::Debug; -use strum_macros::{Display, EnumIter}; +use strum::{Display, EnumIter}; #[derive(Display, Debug, Serialize, Deserialize, Clone, PartialEq, Eq, EnumIter, Hash)] #[cfg_attr(feature = "full", derive(ts_rs::TS))] diff --git a/crates/utils/src/rate_limit/rate_limiter.rs b/crates/utils/src/rate_limit/rate_limiter.rs index 5f1b6f7f5..35c95366d 100644 --- a/crates/utils/src/rate_limit/rate_limiter.rs +++ b/crates/utils/src/rate_limit/rate_limiter.rs @@ -6,7 +6,7 @@ use std::{ net::{IpAddr, Ipv4Addr, Ipv6Addr}, time::Instant, }; -use strum_macros::AsRefStr; +use strum::{AsRefStr, Display}; use tracing::debug; static START_TIME: Lazy = Lazy::new(Instant::now); @@ -66,7 +66,7 @@ impl Bucket { } } -#[derive(Debug, enum_map::Enum, Copy, Clone, AsRefStr)] +#[derive(Debug, enum_map::Enum, Copy, Clone, Display, AsRefStr)] pub enum ActionType { Message, Register, From 32b73193df39b043a7454fa06ad0352fa0eaae4f Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 23 Jul 2024 12:38:54 -0400 Subject: [PATCH 24/69] Make sure you can view your moderated deleted and removed communities. (#4912) * Make sure you can view your moderated deleted and removed communities. - The front end checks to see whether you are a mod, in order to be able to restore deleted / removed communities. This removes a filter which prevents that. - Fixes #4911 * Only show deleted communities to creator, and removed to admins. * Addressing PR comments. --- crates/api_crud/src/site/read.rs | 2 +- crates/apub/src/api/read_person.rs | 2 +- .../src/community_moderator_view.rs | 21 +++++++++++++------ 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index 69e82007c..e8065c08b 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -84,7 +84,7 @@ pub async fn get_site( |pool| CommunityBlockView::for_person(pool, person_id), |pool| InstanceBlockView::for_person(pool, person_id), |pool| PersonBlockView::for_person(pool, person_id), - |pool| CommunityModeratorView::for_person(pool, person_id, true), + |pool| CommunityModeratorView::for_person(pool, person_id, Some(&local_user_view.local_user)), |pool| LocalUserLanguage::read(pool, local_user_id) )) .with_lemmy_type(LemmyErrorType::SystemErrLogin)?; diff --git a/crates/apub/src/api/read_person.rs b/crates/apub/src/api/read_person.rs index 149e06a17..d61f6d9c5 100644 --- a/crates/apub/src/api/read_person.rs +++ b/crates/apub/src/api/read_person.rs @@ -96,7 +96,7 @@ pub async fn read_person( let moderates = CommunityModeratorView::for_person( &mut context.pool(), person_details_id, - local_user_view.is_some(), + local_user_view.map(|l| l.local_user).as_ref(), ) .await?; diff --git a/crates/db_views_actor/src/community_moderator_view.rs b/crates/db_views_actor/src/community_moderator_view.rs index f58e3fee0..f2a59fd9f 100644 --- a/crates/db_views_actor/src/community_moderator_view.rs +++ b/crates/db_views_actor/src/community_moderator_view.rs @@ -2,10 +2,11 @@ use crate::structs::CommunityModeratorView; use diesel::{dsl::exists, result::Error, select, ExpressionMethods, QueryDsl}; use diesel_async::RunQueryDsl; use lemmy_db_schema::{ + impls::local_user::LocalUserOptionHelper, newtypes::{CommunityId, PersonId}, schema::{community, community_moderator, person}, + source::local_user::LocalUser, utils::{get_conn, DbPool}, - CommunityVisibility, }; impl CommunityModeratorView { @@ -60,20 +61,28 @@ impl CommunityModeratorView { pub async fn for_person( pool: &mut DbPool<'_>, person_id: PersonId, - is_authenticated: bool, + local_user: Option<&LocalUser>, ) -> Result, Error> { let conn = &mut get_conn(pool).await?; let mut query = community_moderator::table .inner_join(community::table) .inner_join(person::table) .filter(community_moderator::person_id.eq(person_id)) - .filter(community::deleted.eq(false)) - .filter(community::removed.eq(false)) .select((community::all_columns, person::all_columns)) .into_boxed(); - if !is_authenticated { - query = query.filter(community::visibility.eq(CommunityVisibility::Public)); + + query = local_user.visible_communities_only(query); + + // only show deleted communities to creator + if Some(person_id) != local_user.person_id() { + query = query.filter(community::deleted.eq(false)); } + + // Show removed communities to admins only + if !local_user.is_admin() { + query = query.filter(community::removed.eq(false)) + } + query.load::(conn).await } From 9738d87f38b061ba8c1823106eca0ee8c1e3f0d5 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 23 Jul 2024 19:01:24 -0400 Subject: [PATCH 25/69] Add the ability to fetch a registration application by person_id. (#4913) * Add the ability to fetch a registration application by person_id. - Fixes #4908 * Cleaning up PR. --- .../src/site/registration_applications/get.rs | 28 +++++++++++++++ .../src/site/registration_applications/mod.rs | 1 + crates/api_common/src/site.rs | 21 +++++++++-- .../src/impls/registration_application.rs | 4 +-- crates/db_schema/src/newtypes.rs | 6 ++++ .../src/source/registration_application.rs | 4 +-- .../src/registration_application_view.rs | 35 +++++++++++++------ src/api_routes_http.rs | 5 +++ 8 files changed, 87 insertions(+), 17 deletions(-) create mode 100644 crates/api/src/site/registration_applications/get.rs diff --git a/crates/api/src/site/registration_applications/get.rs b/crates/api/src/site/registration_applications/get.rs new file mode 100644 index 000000000..2d5d6bf5b --- /dev/null +++ b/crates/api/src/site/registration_applications/get.rs @@ -0,0 +1,28 @@ +use actix_web::web::{Data, Json, Query}; +use lemmy_api_common::{ + context::LemmyContext, + site::{GetRegistrationApplication, RegistrationApplicationResponse}, + utils::is_admin, +}; +use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView}; +use lemmy_utils::{error::LemmyResult, LemmyErrorType}; + +/// Lists registration applications, filterable by undenied only. +pub async fn get_registration_application( + data: Query, + context: Data, + local_user_view: LocalUserView, +) -> LemmyResult> { + // Make sure user is an admin + is_admin(&local_user_view)?; + + // Read the view + let registration_application = + RegistrationApplicationView::read_by_person(&mut context.pool(), data.person_id) + .await? + .ok_or(LemmyErrorType::CouldntFindRegistrationApplication)?; + + Ok(Json(RegistrationApplicationResponse { + registration_application, + })) +} diff --git a/crates/api/src/site/registration_applications/mod.rs b/crates/api/src/site/registration_applications/mod.rs index e5082615a..e904f597d 100644 --- a/crates/api/src/site/registration_applications/mod.rs +++ b/crates/api/src/site/registration_applications/mod.rs @@ -1,3 +1,4 @@ pub mod approve; +pub mod get; pub mod list; pub mod unread_count; diff --git a/crates/api_common/src/site.rs b/crates/api_common/src/site.rs index 77bfcd8ee..3850de1c6 100644 --- a/crates/api_common/src/site.rs +++ b/crates/api_common/src/site.rs @@ -1,7 +1,15 @@ use crate::federate_retry_sleep_duration; use chrono::{DateTime, Utc}; use lemmy_db_schema::{ - newtypes::{CommentId, CommunityId, InstanceId, LanguageId, PersonId, PostId}, + newtypes::{ + CommentId, + CommunityId, + InstanceId, + LanguageId, + PersonId, + PostId, + RegistrationApplicationId, + }, source::{ federation_queue_state::FederationQueueState, instance::Instance, @@ -440,13 +448,22 @@ pub struct ListRegistrationApplicationsResponse { pub registration_applications: Vec, } +#[skip_serializing_none] +#[derive(Debug, Serialize, Deserialize, Clone, Copy, Default, PartialEq, Eq, Hash)] +#[cfg_attr(feature = "full", derive(TS))] +#[cfg_attr(feature = "full", ts(export))] +/// Gets a registration application for a person +pub struct GetRegistrationApplication { + pub person_id: PersonId, +} + #[skip_serializing_none] #[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)] #[cfg_attr(feature = "full", derive(TS))] #[cfg_attr(feature = "full", ts(export))] /// Approves a registration application. pub struct ApproveRegistrationApplication { - pub id: i32, + pub id: RegistrationApplicationId, pub approve: bool, pub deny_reason: Option, } diff --git a/crates/db_schema/src/impls/registration_application.rs b/crates/db_schema/src/impls/registration_application.rs index 46b7d4bee..055ffb51f 100644 --- a/crates/db_schema/src/impls/registration_application.rs +++ b/crates/db_schema/src/impls/registration_application.rs @@ -1,6 +1,6 @@ use crate::{ diesel::OptionalExtension, - newtypes::LocalUserId, + newtypes::{LocalUserId, RegistrationApplicationId}, schema::registration_application::dsl::{local_user_id, registration_application}, source::registration_application::{ RegistrationApplication, @@ -17,7 +17,7 @@ use diesel_async::RunQueryDsl; impl Crud for RegistrationApplication { type InsertForm = RegistrationApplicationInsertForm; type UpdateForm = RegistrationApplicationUpdateForm; - type IdType = i32; + type IdType = RegistrationApplicationId; async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result { let conn = &mut get_conn(pool).await?; diff --git a/crates/db_schema/src/newtypes.rs b/crates/db_schema/src/newtypes.rs index 9aeaa5266..c715305bb 100644 --- a/crates/db_schema/src/newtypes.rs +++ b/crates/db_schema/src/newtypes.rs @@ -148,6 +148,12 @@ pub struct LocalSiteId(i32); /// The custom emoji id. pub struct CustomEmojiId(i32); +#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, Default)] +#[cfg_attr(feature = "full", derive(DieselNewType, TS))] +#[cfg_attr(feature = "full", ts(export))] +/// The registration application id. +pub struct RegistrationApplicationId(i32); + #[cfg(feature = "full")] #[derive(Serialize, Deserialize)] #[serde(remote = "Ltree")] diff --git a/crates/db_schema/src/source/registration_application.rs b/crates/db_schema/src/source/registration_application.rs index 2824951d7..2ac973f34 100644 --- a/crates/db_schema/src/source/registration_application.rs +++ b/crates/db_schema/src/source/registration_application.rs @@ -1,4 +1,4 @@ -use crate::newtypes::{LocalUserId, PersonId}; +use crate::newtypes::{LocalUserId, PersonId, RegistrationApplicationId}; #[cfg(feature = "full")] use crate::schema::registration_application; use chrono::{DateTime, Utc}; @@ -15,7 +15,7 @@ use ts_rs::TS; #[cfg_attr(feature = "full", ts(export))] /// A registration application. pub struct RegistrationApplication { - pub id: i32, + pub id: RegistrationApplicationId, pub local_user_id: LocalUserId, pub answer: String, pub admin_id: Option, diff --git a/crates/db_views/src/registration_application_view.rs b/crates/db_views/src/registration_application_view.rs index 9a85d534a..54c7f7598 100644 --- a/crates/db_views/src/registration_application_view.rs +++ b/crates/db_views/src/registration_application_view.rs @@ -11,12 +11,18 @@ use diesel::{ use diesel_async::RunQueryDsl; use lemmy_db_schema::{ aliases, + newtypes::{PersonId, RegistrationApplicationId}, schema::{local_user, person, registration_application}, utils::{get_conn, limit_and_offset, DbConn, DbPool, ListFn, Queries, ReadFn}, }; +enum ReadBy { + Id(RegistrationApplicationId), + Person(PersonId), +} + fn queries<'a>() -> Queries< - impl ReadFn<'a, RegistrationApplicationView, i32>, + impl ReadFn<'a, RegistrationApplicationView, ReadBy>, impl ListFn<'a, RegistrationApplicationView, RegistrationApplicationQuery>, > { let all_joins = |query: registration_application::BoxedQuery<'a, Pg>| { @@ -36,14 +42,15 @@ fn queries<'a>() -> Queries< )) }; - let read = move |mut conn: DbConn<'a>, registration_application_id: i32| async move { - all_joins( - registration_application::table - .find(registration_application_id) - .into_boxed(), - ) - .first(&mut conn) - .await + let read = move |mut conn: DbConn<'a>, search: ReadBy| async move { + let mut query = all_joins(registration_application::table.into_boxed()); + + query = match search { + ReadBy::Id(id) => query.filter(registration_application::id.eq(id)), + ReadBy::Person(person_id) => query.filter(person::id.eq(person_id)), + }; + + query.first(&mut conn).await }; let list = move |mut conn: DbConn<'a>, options: RegistrationApplicationQuery| async move { @@ -76,11 +83,17 @@ fn queries<'a>() -> Queries< impl RegistrationApplicationView { pub async fn read( pool: &mut DbPool<'_>, - registration_application_id: i32, + id: RegistrationApplicationId, ) -> Result, Error> { - queries().read(pool, registration_application_id).await + queries().read(pool, ReadBy::Id(id)).await } + pub async fn read_by_person( + pool: &mut DbPool<'_>, + person_id: PersonId, + ) -> Result, Error> { + queries().read(pool, ReadBy::Person(person_id)).await + } /// Returns the current unread registration_application count pub async fn get_unread_count( pool: &mut DbPool<'_>, diff --git a/src/api_routes_http.rs b/src/api_routes_http.rs index 2a15b4ca6..7b4b34158 100644 --- a/src/api_routes_http.rs +++ b/src/api_routes_http.rs @@ -82,6 +82,7 @@ use lemmy_api::{ }, registration_applications::{ approve::approve_registration_application, + get::get_registration_application, list::list_registration_applications, unread_count::get_unread_registration_application_count, }, @@ -361,6 +362,10 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) { "/registration_application/approve", web::put().to(approve_registration_application), ) + .route( + "/registration_application", + web::get().to(get_registration_application), + ) .route("/list_all_media", web::get().to(list_all_media)) .service( web::scope("/purge") From 7321a6300560262ffb87ebbf2b73720b579a81fc Mon Sep 17 00:00:00 2001 From: John Spurlock Date: Wed, 24 Jul 2024 05:18:28 -0500 Subject: [PATCH 26/69] Fix instance AP outbox url (#4917) //site_outbox to /site_outbox --- crates/apub/src/objects/instance.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/apub/src/objects/instance.rs b/crates/apub/src/objects/instance.rs index 24bb63b4c..6f0a7328d 100644 --- a/crates/apub/src/objects/instance.rs +++ b/crates/apub/src/objects/instance.rs @@ -109,7 +109,7 @@ impl Object for ApubSite { icon: self.icon.clone().map(ImageObject::new), image: self.banner.clone().map(ImageObject::new), inbox: self.inbox_url.clone().into(), - outbox: Url::parse(&format!("{}/site_outbox", self.actor_id))?, + outbox: Url::parse(&format!("{}site_outbox", self.actor_id))?, public_key: self.public_key(), language, content_warning: self.content_warning.clone(), From fb911679d0d662488f7ea4cb433970a24088e947 Mon Sep 17 00:00:00 2001 From: Nutomic Date: Tue, 30 Jul 2024 14:34:17 +0200 Subject: [PATCH 27/69] Fix admin notification for new user registration (fixes #4916) (#4925) --- crates/api/src/local_user/verify_email.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/crates/api/src/local_user/verify_email.rs b/crates/api/src/local_user/verify_email.rs index 5f38ffc12..5b895ec7e 100644 --- a/crates/api/src/local_user/verify_email.rs +++ b/crates/api/src/local_user/verify_email.rs @@ -5,12 +5,9 @@ use lemmy_api_common::{ utils::send_new_applicant_email_to_admins, SuccessResponse, }; -use lemmy_db_schema::{ - source::{ - email_verification::EmailVerification, - local_user::{LocalUser, LocalUserUpdateForm}, - }, - RegistrationMode, +use lemmy_db_schema::source::{ + email_verification::EmailVerification, + local_user::{LocalUser, LocalUserUpdateForm}, }; use lemmy_db_views::structs::{LocalUserView, SiteView}; use lemmy_utils::error::{LemmyErrorType, LemmyResult}; @@ -41,9 +38,7 @@ pub async fn verify_email( EmailVerification::delete_old_tokens_for_local_user(&mut context.pool(), local_user_id).await?; // send out notification about registration application to admins if enabled - if site_view.local_site.registration_mode == RegistrationMode::RequireApplication - && site_view.local_site.application_email_admins - { + if site_view.local_site.application_email_admins { let local_user = LocalUserView::read(&mut context.pool(), local_user_id) .await? .ok_or(LemmyErrorType::CouldntFindPerson)?; From 2ccb46b66daa560efc52fbea4866cee01676fb55 Mon Sep 17 00:00:00 2001 From: abdel-m Date: Tue, 30 Jul 2024 14:34:58 +0200 Subject: [PATCH 28/69] pass local user to send local notifs (#4920) * pass local user to send local notif * pass local user to all crud calls * execution of command "cargo +nightly fmt" * Formatting and mode fixes. --------- Co-authored-by: Dessalines --- crates/api_common/src/build_response.rs | 11 ++++++++--- crates/api_crud/src/comment/create.rs | 1 + crates/api_crud/src/comment/delete.rs | 11 +++++++++-- crates/api_crud/src/comment/remove.rs | 11 +++++++++-- crates/api_crud/src/comment/update.rs | 1 + .../apub/src/activities/create_or_update/comment.rs | 2 +- 6 files changed, 29 insertions(+), 8 deletions(-) diff --git a/crates/api_common/src/build_response.rs b/crates/api_common/src/build_response.rs index 200284b00..8f140f2fe 100644 --- a/crates/api_common/src/build_response.rs +++ b/crates/api_common/src/build_response.rs @@ -100,15 +100,20 @@ pub async fn send_local_notifs( person: &Person, do_send_email: bool, context: &LemmyContext, + local_user_view: Option<&LocalUserView>, ) -> LemmyResult> { let mut recipient_ids = Vec::new(); let inbox_link = format!("{}/inbox", context.settings().get_protocol_and_hostname()); // let person = my_local_user.person; // Read the comment view to get extra info - let comment_view = CommentView::read(&mut context.pool(), comment_id, None) - .await? - .ok_or(LemmyErrorType::CouldntFindComment)?; + let comment_view = CommentView::read( + &mut context.pool(), + comment_id, + local_user_view.map(|view| &view.local_user), + ) + .await? + .ok_or(LemmyErrorType::CouldntFindComment)?; let comment = comment_view.comment; let post = comment_view.post; let community = comment_view.community; diff --git a/crates/api_crud/src/comment/create.rs b/crates/api_crud/src/comment/create.rs index b7c65740c..49de9d5de 100644 --- a/crates/api_crud/src/comment/create.rs +++ b/crates/api_crud/src/comment/create.rs @@ -134,6 +134,7 @@ pub async fn create_comment( &local_user_view.person, true, &context, + Some(&local_user_view), ) .await?; diff --git a/crates/api_crud/src/comment/delete.rs b/crates/api_crud/src/comment/delete.rs index 29706d365..8c81608c8 100644 --- a/crates/api_crud/src/comment/delete.rs +++ b/crates/api_crud/src/comment/delete.rs @@ -59,8 +59,15 @@ pub async fn delete_comment( .await .with_lemmy_type(LemmyErrorType::CouldntUpdateComment)?; - let recipient_ids = - send_local_notifs(vec![], comment_id, &local_user_view.person, false, &context).await?; + let recipient_ids = send_local_notifs( + vec![], + comment_id, + &local_user_view.person, + false, + &context, + Some(&local_user_view), + ) + .await?; let updated_comment_id = updated_comment.id; ActivityChannel::submit_activity( diff --git a/crates/api_crud/src/comment/remove.rs b/crates/api_crud/src/comment/remove.rs index f810c8275..ec4923e93 100644 --- a/crates/api_crud/src/comment/remove.rs +++ b/crates/api_crud/src/comment/remove.rs @@ -81,8 +81,15 @@ pub async fn remove_comment( }; ModRemoveComment::create(&mut context.pool(), &form).await?; - let recipient_ids = - send_local_notifs(vec![], comment_id, &local_user_view.person, false, &context).await?; + let recipient_ids = send_local_notifs( + vec![], + comment_id, + &local_user_view.person, + false, + &context, + Some(&local_user_view), + ) + .await?; let updated_comment_id = updated_comment.id; ActivityChannel::submit_activity( diff --git a/crates/api_crud/src/comment/update.rs b/crates/api_crud/src/comment/update.rs index 32bd08240..ed9460825 100644 --- a/crates/api_crud/src/comment/update.rs +++ b/crates/api_crud/src/comment/update.rs @@ -91,6 +91,7 @@ pub async fn update_comment( &local_user_view.person, false, &context, + Some(&local_user_view), ) .await?; diff --git a/crates/apub/src/activities/create_or_update/comment.rs b/crates/apub/src/activities/create_or_update/comment.rs index 2406d2eb3..89be8d49e 100644 --- a/crates/apub/src/activities/create_or_update/comment.rs +++ b/crates/apub/src/activities/create_or_update/comment.rs @@ -179,7 +179,7 @@ impl ActivityHandler for CreateOrUpdateNote { // TODO: for compatibility with other projects, it would be much better to read this from cc or // tags let mentions = scrape_text_for_mentions(&comment.content); - send_local_notifs(mentions, comment.id, &actor, do_send_email, context).await?; + send_local_notifs(mentions, comment.id, &actor, do_send_email, context, None).await?; Ok(()) } } From 069a9509d5120db19ca8a98e47bb5326df5484e4 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 30 Jul 2024 09:41:06 -0400 Subject: [PATCH 29/69] Adding renovate automerge. (#4927) --- renovate.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/renovate.json b/renovate.json index 1911d651b..8d57f0aa8 100644 --- a/renovate.json +++ b/renovate.json @@ -1,5 +1,6 @@ { "$schema": "https://docs.renovatebot.com/renovate-schema.json", "extends": ["config:recommended"], - "schedule": ["before 4am on the first day of the month"] + "schedule": ["before 4am on the first day of the month"], + "automerge": true } From 1ef375e5c3bb4a22c2e954615772738ae3754421 Mon Sep 17 00:00:00 2001 From: SleeplessOne1917 <28871516+SleeplessOne1917@users.noreply.github.com> Date: Tue, 30 Jul 2024 14:11:39 +0000 Subject: [PATCH 30/69] Replace 3rd party once_cell crate with recently stabilized standard library API (#4919) * Replace 3rd party once_cell crate with recently stabilized standard library API * Bump CI rust version --- .woodpecker.yml | 2 +- Cargo.lock | 164 +++++++++--------- Cargo.toml | 1 - crates/api_common/Cargo.toml | 2 - crates/api_common/src/send_activity.rs | 6 +- crates/api_common/src/utils.rs | 5 +- crates/api_crud/Cargo.toml | 1 - crates/api_crud/src/site/read.rs | 4 +- crates/apub/Cargo.toml | 1 - crates/apub/src/lib.rs | 7 +- crates/db_schema/Cargo.toml | 2 - crates/db_schema/src/impls/local_site.rs | 4 +- crates/db_schema/src/utils.rs | 5 +- crates/federate/Cargo.toml | 1 - crates/federate/src/inboxes.rs | 12 +- crates/federate/src/util.rs | 25 +-- crates/routes/Cargo.toml | 1 - crates/routes/src/feeds.rs | 5 +- crates/utils/Cargo.toml | 2 - crates/utils/src/rate_limit/rate_limiter.rs | 4 +- crates/utils/src/settings/mod.rs | 7 +- crates/utils/src/utils/markdown/mod.rs | 4 +- .../utils/src/utils/markdown/spoiler_rule.rs | 6 +- crates/utils/src/utils/mention.rs | 4 +- crates/utils/src/utils/validation.rs | 18 +- docker/Dockerfile | 2 +- 26 files changed, 145 insertions(+), 150 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index d12f12326..f67c1e44c 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -2,7 +2,7 @@ # See https://github.com/woodpecker-ci/woodpecker/issues/1677 variables: - - &rust_image "rust:1.78" + - &rust_image "rust:1.80" - &rust_nightly_image "rustlang/rust:nightly" - &install_pnpm "corepack enable pnpm" - &slow_check_paths diff --git a/Cargo.lock b/Cargo.lock index c3466f662..efe905559 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -219,7 +219,7 @@ dependencies = [ "actix-utils", "futures-core", "futures-util", - "mio", + "mio 0.8.11", "socket2", "tokio", "tracing", @@ -423,9 +423,9 @@ dependencies = [ [[package]] name = "anstream" -version = "0.6.14" +version = "0.6.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "418c75fa768af9c03be99d17643f93f79bbba589895012a80e3452a19ddda15b" +checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526" dependencies = [ "anstyle", "anstyle-parse", @@ -438,33 +438,33 @@ dependencies = [ [[package]] name = "anstyle" -version = "1.0.7" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "038dfcf04a5feb68e9c60b21c9625a54c2c0616e79b72b0fd87075a056ae1d1b" +checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1" [[package]] name = "anstyle-parse" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03a11a9034d92058ceb6ee011ce58af4a9bf61491aa7e1e59ecd24bd40d22d4" +checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb" dependencies = [ "utf8parse", ] [[package]] name = "anstyle-query" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad186efb764318d35165f1758e7dcef3b10628e26d41a44bc5550652e6804391" +checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a" dependencies = [ "windows-sys 0.52.0", ] [[package]] name = "anstyle-wincon" -version = "3.0.3" +version = "3.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61a38449feb7068f52bb06c12759005cf459ee52bb4adc1d5a7c4322d716fb19" +checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8" dependencies = [ "anstyle", "windows-sys 0.52.0", @@ -970,9 +970,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.9" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64acc1846d54c1fe936a78dc189c34e28d3f5afc348403f28ecf53660b9b8462" +checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" dependencies = [ "clap_builder", "clap_derive", @@ -980,9 +980,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.9" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6fb8393d67ba2e7bfaf28a23458e4e2b543cc73a99595511eb207fdb8aede942" +checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" dependencies = [ "anstream", "anstyle", @@ -992,9 +992,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.8" +version = "4.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2bac35c6dafb060fd4d275d9a4ffae97917c13a6327903a8be2153cd964f7085" +checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -1004,9 +1004,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b82cf0babdbd58558212896d1a4272303a57bdb245c2bf1147185fb45640e70" +checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "clokwerk" @@ -1061,9 +1061,9 @@ checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] name = "colorchoice" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0" [[package]] name = "combine" @@ -1096,7 +1096,7 @@ dependencies = [ "ron", "serde", "serde_json", - "toml 0.8.15", + "toml 0.8.16", "yaml-rust", ] @@ -2435,7 +2435,7 @@ dependencies = [ "http 1.1.0", "hyper 1.4.1", "hyper-util", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", "tokio-rustls 0.26.0", @@ -2630,9 +2630,9 @@ checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] name = "is_terminal_polyfill" -version = "1.70.0" +version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8478577c03552c21db0e2724ffb8986a5ce7af88107e6be5d2ee6e158c12800" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" [[package]] name = "itertools" @@ -2689,9 +2689,9 @@ checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" [[package]] name = "jobserver" -version = "0.1.31" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2b099aaa34a9751c5bf0878add70444e1ed2dd73f347be99003d4577277de6e" +checksum = "48d1dbcbbeb6a7fec7e059840aa538bd62aaccf972c7346c4d9d2059312853d0" dependencies = [ "libc", ] @@ -2790,7 +2790,6 @@ dependencies = [ "lemmy_utils", "mime", "moka", - "once_cell", "pretty_assertions", "regex", "reqwest 0.11.27", @@ -2824,7 +2823,6 @@ dependencies = [ "lemmy_db_views_actor", "lemmy_utils", "moka", - "once_cell", "tracing", "url", "uuid", @@ -2854,7 +2852,6 @@ dependencies = [ "lemmy_db_views_actor", "lemmy_utils", "moka", - "once_cell", "pretty_assertions", "reqwest 0.11.27", "serde", @@ -2905,10 +2902,9 @@ dependencies = [ "i-love-jesus", "lemmy_utils", "moka", - "once_cell", "pretty_assertions", "regex", - "rustls 0.23.11", + "rustls 0.23.12", "serde", "serde_json", "serde_with", @@ -2997,7 +2993,6 @@ dependencies = [ "lemmy_utils", "mockall", "moka", - "once_cell", "reqwest 0.11.27", "serde_json", "serial_test", @@ -3024,7 +3019,6 @@ dependencies = [ "lemmy_db_views", "lemmy_db_views_actor", "lemmy_utils", - "once_cell", "reqwest 0.11.27", "reqwest-middleware 0.2.5", "rss", @@ -3066,7 +3060,7 @@ dependencies = [ "reqwest 0.11.27", "reqwest-middleware 0.2.5", "reqwest-tracing 0.4.8", - "rustls 0.23.11", + "rustls 0.23.12", "serde_json", "serial_test", "tokio", @@ -3096,7 +3090,6 @@ dependencies = [ "itertools 0.13.0", "lettre", "markdown-it", - "once_cell", "pretty_assertions", "regex", "reqwest 0.11.27", @@ -3136,7 +3129,7 @@ dependencies = [ "nom", "percent-encoding", "quoted_printable", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pemfile 2.1.2", "socket2", "tokio", @@ -3473,6 +3466,18 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "mio" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +dependencies = [ + "hermit-abi", + "libc", + "wasi", + "windows-sys 0.52.0", +] + [[package]] name = "mirai-annotations" version = "1.12.0" @@ -4108,7 +4113,7 @@ dependencies = [ "reqwest 0.12.5", "reqwest-middleware 0.3.2", "reqwest-tracing 0.5.2", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-channel-resolver", "rustls-pemfile 2.1.2", "rusty-s3", @@ -4126,7 +4131,7 @@ dependencies = [ "tokio-postgres", "tokio-postgres-generic-rustls", "tokio-util", - "toml 0.8.15", + "toml 0.8.16", "tracing", "tracing-actix-web", "tracing-error", @@ -4305,9 +4310,9 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] name = "predicates" -version = "3.1.0" +version = "3.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b87bfd4605926cdfefc1c3b5f8fe560e3feca9d5552cf68c466d3d8236c7e8" +checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97" dependencies = [ "anstyle", "predicates-core", @@ -4315,15 +4320,15 @@ dependencies = [ [[package]] name = "predicates-core" -version = "1.0.6" +version = "1.0.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b794032607612e7abeb4db69adb4e33590fa6cf1149e95fd7cb00e634b92f174" +checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931" [[package]] name = "predicates-tree" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "368ba315fb8c5052ab692e68a0eefec6ec57b23a36959c14496f0b0df2c0cecf" +checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13" dependencies = [ "predicates-core", "termtree", @@ -4523,7 +4528,7 @@ dependencies = [ "quinn-proto", "quinn-udp", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "thiserror", "tokio", "tracing", @@ -4539,7 +4544,7 @@ dependencies = [ "rand", "ring", "rustc-hash", - "rustls 0.23.11", + "rustls 0.23.12", "slab", "thiserror", "tinyvec", @@ -4548,9 +4553,9 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.3" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25a78e6f726d84fcf960409f509ae354a32648f090c8d32a2ea8b1a1bc3bab14" +checksum = "8bffec3605b73c6f1754535084a85229fa8a30f86014e6c81aeec4abb68b0285" dependencies = [ "libc", "once_cell", @@ -4677,7 +4682,7 @@ dependencies = [ "time", "tokio", "tokio-postgres", - "toml 0.8.15", + "toml 0.8.16", "url", "walkdir", ] @@ -4818,7 +4823,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pemfile 2.1.2", "rustls-pki-types", "serde", @@ -5044,9 +5049,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.11" +version = "0.23.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4828ea528154ae444e5a642dbb7d5623354030dc9822b83fd9bb79683c7399d0" +checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" dependencies = [ "aws-lc-rs", "log", @@ -5065,7 +5070,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fede2a247359da6b4998f7723ec6468c2d6a577a5d8c17e54f21806426ad2290" dependencies = [ "nanorand", - "rustls 0.23.11", + "rustls 0.23.12", ] [[package]] @@ -5157,9 +5162,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.4" +version = "2.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4465c22496331e20eb047ff46e7366455bc01c0c02015c4a376de0b2cd3a1af" +checksum = "1fadf67e3cf23f8b11a6c8c48a16cb2437381503615acd91094ec7b4686a5a53" dependencies = [ "sdd", ] @@ -5297,9 +5302,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79e674e01f999af37c49f70a6ede167a8a60b2503e56c5599532a65baa5969a0" +checksum = "eb5b1b31579f3811bf615c144393417496f152e12ac8b7663bf664f4a815306d" dependencies = [ "serde", ] @@ -5909,22 +5914,21 @@ dependencies = [ [[package]] name = "tokio" -version = "1.38.1" +version = "1.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2caba9f80616f438e09748d5acda951967e1ea58508ef53d9c6402485a46df" +checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" dependencies = [ "backtrace", "bytes", "libc", - "mio", - "num_cpus", + "mio 1.0.1", "parking_lot 0.12.3", "pin-project-lite", "signal-hook-registry", "socket2", "tokio-macros", "tracing", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -5939,9 +5943,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "2.3.0" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f5ae998a069d4b5aba8ee9dad856af7d520c3699e6159b185c2acd48155d39a" +checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752" dependencies = [ "proc-macro2", "quote", @@ -5991,7 +5995,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8e98c31c29b2666fb28720739e11476166be4ead1610a37dcd7414bb124413a" dependencies = [ "aws-lc-rs", - "rustls 0.23.11", + "rustls 0.23.12", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -6005,7 +6009,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04fb792ccd6bbcd4bba408eb8a292f70fc4a3589e5d793626f45190e6454b6ab" dependencies = [ "ring", - "rustls 0.23.11", + "rustls 0.23.12", "tokio", "tokio-postgres", "tokio-rustls 0.26.0", @@ -6028,7 +6032,7 @@ version = "0.26.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0c7bc40d0e5a97695bb96e27995cd3a08538541b0a846f65bba7a359f36700d4" dependencies = [ - "rustls 0.23.11", + "rustls 0.23.12", "rustls-pki-types", "tokio", ] @@ -6071,21 +6075,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac2caab0bf757388c6c0ae23b3293fdb463fee59434529014f85e3263b995c28" +checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.16", + "toml_edit 0.22.17", ] [[package]] name = "toml_datetime" -version = "0.6.6" +version = "0.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4badfd56924ae69bcc9039335b2e017639ce3f9b001c393c1b2d1ef846ce2cbf" +checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" dependencies = [ "serde", ] @@ -6105,15 +6109,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.16" +version = "0.22.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278f3d518e152219c994ce877758516bca5e118eaed6996192a774fb9fbf0788" +checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" dependencies = [ "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.14", + "winnow 0.6.16", ] [[package]] @@ -6204,9 +6208,9 @@ dependencies = [ [[package]] name = "totp-rs" -version = "5.5.1" +version = "5.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c4ae9724c5888c0417d2396037ed3b60665925624766416e3e342b6ba5dbd3f" +checksum = "17b2f27dad992486c26b4e7455f38aa487e838d6d61b57e72906ee2b8c287a90" dependencies = [ "base32", "constant_time_eq", @@ -7015,9 +7019,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.14" +version = "0.6.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374ec40a2d767a3c1b4972d9475ecd557356637be906f2cb3f7fe17a6eb5e22f" +checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 96c4e2800..5c4ea3819 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -146,7 +146,6 @@ typed-builder = "0.18.2" serial_test = "3.1.1" tokio = { version = "1.38.0", features = ["full"] } regex = "1.10.4" -once_cell = "1.19.0" diesel-derive-newtype = "2.1.2" diesel-derive-enum = { version = "2.1.0", features = ["postgres"] } strum = { version = "0.26.3", features = ["derive"] } diff --git a/crates/api_common/Cargo.toml b/crates/api_common/Cargo.toml index 25bc02893..4eabfe5f9 100644 --- a/crates/api_common/Cargo.toml +++ b/crates/api_common/Cargo.toml @@ -34,7 +34,6 @@ full = [ "reqwest", "actix-web", "futures", - "once_cell", "jsonwebtoken", "mime", ] @@ -61,7 +60,6 @@ reqwest = { workspace = true, optional = true } ts-rs = { workspace = true, optional = true } moka.workspace = true anyhow.workspace = true -once_cell = { workspace = true, optional = true } actix-web = { workspace = true, optional = true } enum-map = { workspace = true } urlencoding = { workspace = true } diff --git a/crates/api_common/src/send_activity.rs b/crates/api_common/src/send_activity.rs index a8b75d4b5..02518ca33 100644 --- a/crates/api_common/src/send_activity.rs +++ b/crates/api_common/src/send_activity.rs @@ -13,7 +13,7 @@ use lemmy_db_schema::{ }; use lemmy_db_views::structs::PrivateMessageView; use lemmy_utils::error::LemmyResult; -use once_cell::sync::{Lazy, OnceCell}; +use std::sync::{LazyLock, OnceLock}; use tokio::{ sync::{ mpsc, @@ -28,7 +28,7 @@ type MatchOutgoingActivitiesBoxed = Box fn(SendActivityData, &'a Data) -> BoxFuture<'a, LemmyResult<()>>>; /// This static is necessary so that the api_common crates don't need to depend on lemmy_apub -pub static MATCH_OUTGOING_ACTIVITIES: OnceCell = OnceCell::new(); +pub static MATCH_OUTGOING_ACTIVITIES: OnceLock = OnceLock::new(); #[derive(Debug)] pub enum SendActivityData { @@ -101,7 +101,7 @@ pub enum SendActivityData { // TODO: instead of static, move this into LemmyContext. make sure that stopping the process with // ctrl+c still works. -static ACTIVITY_CHANNEL: Lazy = Lazy::new(|| { +static ACTIVITY_CHANNEL: LazyLock = LazyLock::new(|| { let (sender, receiver) = mpsc::unbounded_channel(); let weak_sender = sender.downgrade(); ActivityChannel { diff --git a/crates/api_common/src/utils.rs b/crates/api_common/src/utils.rs index 97b12cc5b..0b8e56273 100644 --- a/crates/api_common/src/utils.rs +++ b/crates/api_common/src/utils.rs @@ -53,10 +53,9 @@ use lemmy_utils::{ CACHE_DURATION_FEDERATION, }; use moka::future::Cache; -use once_cell::sync::Lazy; use regex::{escape, Regex, RegexSet}; use rosetta_i18n::{Language, LanguageId}; -use std::collections::HashSet; +use std::{collections::HashSet, sync::LazyLock}; use tracing::warn; use url::{ParseError, Url}; use urlencoding::encode; @@ -546,7 +545,7 @@ pub fn local_site_opt_to_sensitive(local_site: &Option) -> bool { } pub async fn get_url_blocklist(context: &LemmyContext) -> LemmyResult { - static URL_BLOCKLIST: Lazy> = Lazy::new(|| { + static URL_BLOCKLIST: LazyLock> = LazyLock::new(|| { Cache::builder() .max_capacity(1) .time_to_live(CACHE_DURATION_FEDERATION) diff --git a/crates/api_crud/Cargo.toml b/crates/api_crud/Cargo.toml index af50c5648..6055f9ef0 100644 --- a/crates/api_crud/Cargo.toml +++ b/crates/api_crud/Cargo.toml @@ -26,7 +26,6 @@ url = { workspace = true } futures.workspace = true uuid = { workspace = true } moka.workspace = true -once_cell.workspace = true anyhow.workspace = true webmention = "0.5.0" accept-language = "3.1.0" diff --git a/crates/api_crud/src/site/read.rs b/crates/api_crud/src/site/read.rs index e8065c08b..c633bebde 100644 --- a/crates/api_crud/src/site/read.rs +++ b/crates/api_crud/src/site/read.rs @@ -24,14 +24,14 @@ use lemmy_utils::{ VERSION, }; use moka::future::Cache; -use once_cell::sync::Lazy; +use std::sync::LazyLock; #[tracing::instrument(skip(context))] pub async fn get_site( local_user_view: Option, context: Data, ) -> LemmyResult> { - static CACHE: Lazy> = Lazy::new(|| { + static CACHE: LazyLock> = LazyLock::new(|| { Cache::builder() .max_capacity(1) .time_to_live(CACHE_DURATION_API) diff --git a/crates/apub/Cargo.toml b/crates/apub/Cargo.toml index 8f245d076..660489a68 100644 --- a/crates/apub/Cargo.toml +++ b/crates/apub/Cargo.toml @@ -40,7 +40,6 @@ uuid = { workspace = true } async-trait = { workspace = true } anyhow = { workspace = true } reqwest = { workspace = true } -once_cell = { workspace = true } moka.workspace = true serde_with.workspace = true html2md = "0.2.14" diff --git a/crates/apub/src/lib.rs b/crates/apub/src/lib.rs index c8960b008..c8506da52 100644 --- a/crates/apub/src/lib.rs +++ b/crates/apub/src/lib.rs @@ -14,9 +14,8 @@ use lemmy_utils::{ CACHE_DURATION_FEDERATION, }; use moka::future::Cache; -use once_cell::sync::Lazy; use serde_json::Value; -use std::sync::Arc; +use std::sync::{Arc, LazyLock}; use url::Url; pub mod activities; @@ -36,7 +35,7 @@ pub const FEDERATION_HTTP_FETCH_LIMIT: u32 = 100; /// Only include a basic context to save space and bandwidth. The main context is hosted statically /// on join-lemmy.org. Include activitystreams explicitly for better compat, but this could /// theoretically also be moved. -pub static FEDERATION_CONTEXT: Lazy = Lazy::new(|| { +pub static FEDERATION_CONTEXT: LazyLock = LazyLock::new(|| { Value::Array(vec![ Value::String("https://join-lemmy.org/context.json".to_string()), Value::String("https://www.w3.org/ns/activitystreams".to_string()), @@ -129,7 +128,7 @@ pub(crate) async fn local_site_data_cached( // multiple times. This causes a huge number of database reads if we hit the db directly. So we // cache these values for a short time, which will already make a huge difference and ensures that // changes take effect quickly. - static CACHE: Lazy>> = Lazy::new(|| { + static CACHE: LazyLock>> = LazyLock::new(|| { Cache::builder() .max_capacity(1) .time_to_live(CACHE_DURATION_FEDERATION) diff --git a/crates/db_schema/Cargo.toml b/crates/db_schema/Cargo.toml index bf7a8c9b2..57af68f46 100644 --- a/crates/db_schema/Cargo.toml +++ b/crates/db_schema/Cargo.toml @@ -27,7 +27,6 @@ full = [ "lemmy_utils", "activitypub_federation", "regex", - "once_cell", "serde_json", "diesel_ltree", "diesel-async", @@ -64,7 +63,6 @@ diesel-async = { workspace = true, features = [ "deadpool", ], optional = true } regex = { workspace = true, optional = true } -once_cell = { workspace = true, optional = true } diesel_ltree = { workspace = true, optional = true } typed-builder = { workspace = true } async-trait = { workspace = true } diff --git a/crates/db_schema/src/impls/local_site.rs b/crates/db_schema/src/impls/local_site.rs index 602dfe1f4..926814c48 100644 --- a/crates/db_schema/src/impls/local_site.rs +++ b/crates/db_schema/src/impls/local_site.rs @@ -7,7 +7,7 @@ use diesel::{dsl::insert_into, result::Error}; use diesel_async::RunQueryDsl; use lemmy_utils::{error::LemmyResult, CACHE_DURATION_API}; use moka::future::Cache; -use once_cell::sync::Lazy; +use std::sync::LazyLock; impl LocalSite { pub async fn create(pool: &mut DbPool<'_>, form: &LocalSiteInsertForm) -> Result { @@ -18,7 +18,7 @@ impl LocalSite { .await } pub async fn read(pool: &mut DbPool<'_>) -> LemmyResult { - static CACHE: Lazy> = Lazy::new(|| { + static CACHE: LazyLock> = LazyLock::new(|| { Cache::builder() .max_capacity(1) .time_to_live(CACHE_DURATION_API) diff --git a/crates/db_schema/src/utils.rs b/crates/db_schema/src/utils.rs index bcddce19b..b71c43495 100644 --- a/crates/db_schema/src/utils.rs +++ b/crates/db_schema/src/utils.rs @@ -32,7 +32,6 @@ use lemmy_utils::{ settings::SETTINGS, utils::validation::clean_url_params, }; -use once_cell::sync::Lazy; use regex::Regex; use rustls::{ client::danger::{ @@ -49,7 +48,7 @@ use rustls::{ }; use std::{ ops::{Deref, DerefMut}, - sync::Arc, + sync::{Arc, LazyLock}, time::Duration, }; use tracing::error; @@ -478,7 +477,7 @@ pub fn post_to_comment_sort_type(sort: SortType) -> CommentSortType { } } -static EMAIL_REGEX: Lazy = Lazy::new(|| { +static EMAIL_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$") .expect("compile email regex") }); diff --git a/crates/federate/Cargo.toml b/crates/federate/Cargo.toml index b8b438901..8ffda2dae 100644 --- a/crates/federate/Cargo.toml +++ b/crates/federate/Cargo.toml @@ -27,7 +27,6 @@ futures.workspace = true chrono.workspace = true diesel = { workspace = true, features = ["postgres", "chrono", "serde_json"] } diesel-async = { workspace = true, features = ["deadpool", "postgres"] } -once_cell.workspace = true reqwest.workspace = true serde_json.workspace = true tokio = { workspace = true, features = ["full"] } diff --git a/crates/federate/src/inboxes.rs b/crates/federate/src/inboxes.rs index 9869e5270..cda4da39b 100644 --- a/crates/federate/src/inboxes.rs +++ b/crates/federate/src/inboxes.rs @@ -8,9 +8,11 @@ use lemmy_db_schema::{ utils::{ActualDbPool, DbPool}, }; use lemmy_db_views_actor::structs::CommunityFollowerView; -use once_cell::sync::Lazy; use reqwest::Url; -use std::collections::{HashMap, HashSet}; +use std::{ + collections::{HashMap, HashSet}, + sync::LazyLock, +}; /// interval with which new additions to community_followers are queried. /// @@ -21,7 +23,7 @@ use std::collections::{HashMap, HashSet}; /// currently fairly high because of the current structure of storing inboxes for every person, not /// having a separate list of shared_inboxes, and the architecture of having every instance queue be /// fully separate. (see https://github.com/LemmyNet/lemmy/issues/3958) -static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = Lazy::new(|| { +static FOLLOW_ADDITIONS_RECHECK_DELAY: LazyLock = LazyLock::new(|| { if *LEMMY_TEST_FAST_FEDERATION { chrono::TimeDelta::try_seconds(1).expect("TimeDelta out of bounds") } else { @@ -31,8 +33,8 @@ static FOLLOW_ADDITIONS_RECHECK_DELAY: Lazy = Lazy::new(|| { /// The same as FOLLOW_ADDITIONS_RECHECK_DELAY, but triggering when the last person on an instance /// unfollows a specific remote community. This is expected to happen pretty rarely and updating it /// in a timely manner is not too important. -static FOLLOW_REMOVALS_RECHECK_DELAY: Lazy = - Lazy::new(|| chrono::TimeDelta::try_hours(1).expect("TimeDelta out of bounds")); +static FOLLOW_REMOVALS_RECHECK_DELAY: LazyLock = + LazyLock::new(|| chrono::TimeDelta::try_hours(1).expect("TimeDelta out of bounds")); #[async_trait] pub trait DataSource: Send + Sync { diff --git a/crates/federate/src/util.rs b/crates/federate/src/util.rs index afbe957a5..e10a01c30 100644 --- a/crates/federate/src/util.rs +++ b/crates/federate/src/util.rs @@ -18,10 +18,15 @@ use lemmy_db_schema::{ utils::{get_conn, DbPool}, }; use moka::future::Cache; -use once_cell::sync::Lazy; use reqwest::Url; use serde_json::Value; -use std::{fmt::Debug, future::Future, pin::Pin, sync::Arc, time::Duration}; +use std::{ + fmt::Debug, + future::Future, + pin::Pin, + sync::{Arc, LazyLock}, + time::Duration, +}; use tokio::{task::JoinHandle, time::sleep}; use tokio_util::sync::CancellationToken; @@ -29,7 +34,7 @@ use tokio_util::sync::CancellationToken; /// Should only be used for federation tests since it significantly increases CPU and DB load of the /// federation queue. This is intentionally a separate flag from other flags like debug_assertions, /// since this is a invasive change we only need rarely. -pub(crate) static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { +pub(crate) static LEMMY_TEST_FAST_FEDERATION: LazyLock = LazyLock::new(|| { std::env::var("LEMMY_TEST_FAST_FEDERATION") .map(|s| !s.is_empty()) .unwrap_or(false) @@ -49,7 +54,7 @@ pub(crate) static LEMMY_TEST_FAST_FEDERATION: Lazy = Lazy::new(|| { /// If the delay is too short, the workers (one per federated instance) will wake up too /// often and consume a lot of CPU. If the delay is long, then activities on low-traffic instances /// will on average take delay/2 seconds to federate. -pub(crate) static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { +pub(crate) static WORK_FINISHED_RECHECK_DELAY: LazyLock = LazyLock::new(|| { if *LEMMY_TEST_FAST_FEDERATION { Duration::from_millis(100) } else { @@ -61,7 +66,7 @@ pub(crate) static WORK_FINISHED_RECHECK_DELAY: Lazy = Lazy::new(|| { /// /// This cache is common to all the instance workers and prevents there from being more than one /// call per N seconds between each DB query to find max(activity_id). -pub(crate) static CACHE_DURATION_LATEST_ID: Lazy = Lazy::new(|| { +pub(crate) static CACHE_DURATION_LATEST_ID: LazyLock = LazyLock::new(|| { if *LEMMY_TEST_FAST_FEDERATION { // in test mode, we use the same cache duration as the recheck delay so when recheck happens // data is fresh, accelerating the time the tests take. @@ -132,8 +137,8 @@ pub(crate) async fn get_actor_cached( actor_type: ActorType, actor_apub_id: &Url, ) -> Result> { - static CACHE: Lazy>> = - Lazy::new(|| Cache::builder().max_capacity(10000).build()); + static CACHE: LazyLock>> = + LazyLock::new(|| Cache::builder().max_capacity(10000).build()); CACHE .try_get_with(actor_apub_id.clone(), async { let url = actor_apub_id.clone().into(); @@ -172,8 +177,8 @@ pub(crate) async fn get_activity_cached( pool: &mut DbPool<'_>, activity_id: ActivityId, ) -> Result { - static ACTIVITIES: Lazy> = - Lazy::new(|| Cache::builder().max_capacity(10000).build()); + static ACTIVITIES: LazyLock> = + LazyLock::new(|| Cache::builder().max_capacity(10000).build()); ACTIVITIES .try_get_with(activity_id, async { let row = SentActivity::read(pool, activity_id) @@ -195,7 +200,7 @@ pub(crate) async fn get_activity_cached( /// return the most current activity id (with 1 second cache) pub(crate) async fn get_latest_activity_id(pool: &mut DbPool<'_>) -> Result { - static CACHE: Lazy> = Lazy::new(|| { + static CACHE: LazyLock> = LazyLock::new(|| { Cache::builder() .time_to_live(*CACHE_DURATION_LATEST_ID) .build() diff --git a/crates/routes/Cargo.toml b/crates/routes/Cargo.toml index 0d18e4f1f..a614ba42d 100644 --- a/crates/routes/Cargo.toml +++ b/crates/routes/Cargo.toml @@ -30,7 +30,6 @@ reqwest = { workspace = true, features = ["stream"] } reqwest-middleware = { workspace = true } serde = { workspace = true } url = { workspace = true } -once_cell = { workspace = true } tracing = { workspace = true } tokio = { workspace = true } urlencoding = { workspace = true } diff --git a/crates/routes/src/feeds.rs b/crates/routes/src/feeds.rs index f08f28c4a..f7e7d4059 100644 --- a/crates/routes/src/feeds.rs +++ b/crates/routes/src/feeds.rs @@ -25,7 +25,6 @@ use lemmy_utils::{ error::{LemmyError, LemmyErrorType, LemmyResult}, utils::markdown::{markdown_to_html, sanitize_html}, }; -use once_cell::sync::Lazy; use rss::{ extension::{dublincore::DublinCoreExtension, ExtensionBuilder, ExtensionMap}, Channel, @@ -34,7 +33,7 @@ use rss::{ Item, }; use serde::Deserialize; -use std::{collections::BTreeMap, str::FromStr}; +use std::{collections::BTreeMap, str::FromStr, sync::LazyLock}; const RSS_FETCH_LIMIT: i64 = 20; @@ -80,7 +79,7 @@ pub fn config(cfg: &mut web::ServiceConfig) { ); } -static RSS_NAMESPACE: Lazy> = Lazy::new(|| { +static RSS_NAMESPACE: LazyLock> = LazyLock::new(|| { let mut h = BTreeMap::new(); h.insert( "dc".to_string(), diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 1b71b577a..9125f34a2 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -39,7 +39,6 @@ full = [ "dep:urlencoding", "dep:doku", "dep:url", - "dep:once_cell", "dep:smart-default", "dep:enum-map", "dep:futures", @@ -58,7 +57,6 @@ tracing-error = { workspace = true, optional = true } itertools = { workspace = true, optional = true } serde = { workspace = true } serde_json = { workspace = true, optional = true } -once_cell = { workspace = true, optional = true } url = { workspace = true, optional = true } actix-web = { workspace = true, optional = true } anyhow = { workspace = true, optional = true } diff --git a/crates/utils/src/rate_limit/rate_limiter.rs b/crates/utils/src/rate_limit/rate_limiter.rs index 35c95366d..a3c6f6a27 100644 --- a/crates/utils/src/rate_limit/rate_limiter.rs +++ b/crates/utils/src/rate_limit/rate_limiter.rs @@ -1,15 +1,15 @@ use enum_map::EnumMap; -use once_cell::sync::Lazy; use std::{ collections::HashMap, hash::Hash, net::{IpAddr, Ipv4Addr, Ipv6Addr}, + sync::LazyLock, time::Instant, }; use strum::{AsRefStr, Display}; use tracing::debug; -static START_TIME: Lazy = Lazy::new(Instant::now); +static START_TIME: LazyLock = LazyLock::new(Instant::now); /// Smaller than `std::time::Instant` because it uses a smaller integer for seconds and doesn't /// store nanoseconds diff --git a/crates/utils/src/settings/mod.rs b/crates/utils/src/settings/mod.rs index 6efa3fdd3..aba1a4fb1 100644 --- a/crates/utils/src/settings/mod.rs +++ b/crates/utils/src/settings/mod.rs @@ -1,9 +1,8 @@ use crate::{error::LemmyResult, location_info}; use anyhow::{anyhow, Context}; use deser_hjson::from_str; -use once_cell::sync::Lazy; use regex::Regex; -use std::{env, fs, io::Error}; +use std::{env, fs, io::Error, sync::LazyLock}; use urlencoding::encode; pub mod structs; @@ -12,7 +11,7 @@ use structs::{DatabaseConnection, PictrsConfig, PictrsImageMode, Settings}; static DEFAULT_CONFIG_FILE: &str = "config/config.hjson"; -pub static SETTINGS: Lazy = Lazy::new(|| { +pub static SETTINGS: LazyLock = LazyLock::new(|| { if env::var("LEMMY_INITIALIZE_WITH_DEFAULT_SETTINGS").is_ok() { println!( "LEMMY_INITIALIZE_WITH_DEFAULT_SETTINGS was set, any configuration file has been ignored." @@ -24,7 +23,7 @@ pub static SETTINGS: Lazy = Lazy::new(|| { } }); -static WEBFINGER_REGEX: Lazy = Lazy::new(|| { +static WEBFINGER_REGEX: LazyLock = LazyLock::new(|| { Regex::new(&format!( "^acct:([a-zA-Z0-9_]{{3,}})@{}$", SETTINGS.hostname diff --git a/crates/utils/src/utils/markdown/mod.rs b/crates/utils/src/utils/markdown/mod.rs index 87e2cb3a2..7ed553e06 100644 --- a/crates/utils/src/utils/markdown/mod.rs +++ b/crates/utils/src/utils/markdown/mod.rs @@ -1,14 +1,14 @@ use crate::{error::LemmyResult, settings::SETTINGS, LemmyErrorType}; use markdown_it::{plugins::cmark::inline::image::Image, MarkdownIt}; -use once_cell::sync::Lazy; use regex::RegexSet; +use std::sync::LazyLock; use url::Url; use urlencoding::encode; mod link_rule; mod spoiler_rule; -static MARKDOWN_PARSER: Lazy = Lazy::new(|| { +static MARKDOWN_PARSER: LazyLock = LazyLock::new(|| { let mut parser = MarkdownIt::new(); markdown_it::plugins::cmark::add(&mut parser); markdown_it::plugins::extra::add(&mut parser); diff --git a/crates/utils/src/utils/markdown/spoiler_rule.rs b/crates/utils/src/utils/markdown/spoiler_rule.rs index 3f12807fd..caced310a 100644 --- a/crates/utils/src/utils/markdown/spoiler_rule.rs +++ b/crates/utils/src/utils/markdown/spoiler_rule.rs @@ -34,8 +34,8 @@ use markdown_it::{ NodeValue, Renderer, }; -use once_cell::sync::Lazy; use regex::Regex; +use std::sync::LazyLock; #[derive(Debug)] struct SpoilerBlock { @@ -46,8 +46,8 @@ const SPOILER_PREFIX: &str = "::: spoiler "; const SPOILER_SUFFIX: &str = ":::"; const SPOILER_SUFFIX_NEWLINE: &str = ":::\n"; -static SPOILER_REGEX: Lazy = - Lazy::new(|| Regex::new(r"^::: spoiler .*$").expect("compile spoiler markdown regex.")); +static SPOILER_REGEX: LazyLock = + LazyLock::new(|| Regex::new(r"^::: spoiler .*$").expect("compile spoiler markdown regex.")); impl NodeValue for SpoilerBlock { // Formats any node marked as a 'SpoilerBlock' into HTML. diff --git a/crates/utils/src/utils/mention.rs b/crates/utils/src/utils/mention.rs index 7e5e5f27c..c7cc2043f 100644 --- a/crates/utils/src/utils/mention.rs +++ b/crates/utils/src/utils/mention.rs @@ -1,8 +1,8 @@ use itertools::Itertools; -use once_cell::sync::Lazy; use regex::Regex; +use std::sync::LazyLock; -static MENTIONS_REGEX: Lazy = Lazy::new(|| { +static MENTIONS_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"@(?P[\w.]+)@(?P[a-zA-Z0-9._:-]+)").expect("compile regex") }); // TODO nothing is done with community / group webfingers yet, so just ignore those for now diff --git a/crates/utils/src/utils/validation.rs b/crates/utils/src/utils/validation.rs index 8891411a5..2f9e27f5c 100644 --- a/crates/utils/src/utils/validation.rs +++ b/crates/utils/src/utils/validation.rs @@ -1,16 +1,16 @@ use crate::error::{LemmyErrorExt, LemmyErrorType, LemmyResult}; use itertools::Itertools; -use once_cell::sync::Lazy; use regex::{Regex, RegexBuilder, RegexSet}; +use std::sync::LazyLock; use url::{ParseError, Url}; // From here: https://github.com/vector-im/element-android/blob/develop/matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/MatrixPatterns.kt#L35 -static VALID_MATRIX_ID_REGEX: Lazy = Lazy::new(|| { +static VALID_MATRIX_ID_REGEX: LazyLock = LazyLock::new(|| { Regex::new(r"^@[A-Za-z0-9\x21-\x39\x3B-\x7F]+:[A-Za-z0-9.-]+(:[0-9]{2,5})?$") .expect("compile regex") }); // taken from https://en.wikipedia.org/wiki/UTM_parameters -static CLEAN_URL_PARAMS_REGEX: Lazy = Lazy::new(|| { +static CLEAN_URL_PARAMS_REGEX: LazyLock = LazyLock::new(|| { Regex::new( r"^(utm_source|utm_medium|utm_campaign|utm_term|utm_content|gclid|gclsrc|dclid|fbclid)=", ) @@ -87,12 +87,12 @@ fn has_newline(name: &str) -> bool { } pub fn is_valid_actor_name(name: &str, actor_name_max_length: usize) -> LemmyResult<()> { - static VALID_ACTOR_NAME_REGEX_EN: Lazy = - Lazy::new(|| Regex::new(r"^[a-zA-Z0-9_]{3,}$").expect("compile regex")); - static VALID_ACTOR_NAME_REGEX_AR: Lazy = - Lazy::new(|| Regex::new(r"^[\p{Arabic}0-9_]{3,}$").expect("compile regex")); - static VALID_ACTOR_NAME_REGEX_RU: Lazy = - Lazy::new(|| Regex::new(r"^[\p{Cyrillic}0-9_]{3,}$").expect("compile regex")); + static VALID_ACTOR_NAME_REGEX_EN: LazyLock = + LazyLock::new(|| Regex::new(r"^[a-zA-Z0-9_]{3,}$").expect("compile regex")); + static VALID_ACTOR_NAME_REGEX_AR: LazyLock = + LazyLock::new(|| Regex::new(r"^[\p{Arabic}0-9_]{3,}$").expect("compile regex")); + static VALID_ACTOR_NAME_REGEX_RU: LazyLock = + LazyLock::new(|| Regex::new(r"^[\p{Cyrillic}0-9_]{3,}$").expect("compile regex")); let check = name.chars().count() <= actor_name_max_length && !has_newline(name); diff --git a/docker/Dockerfile b/docker/Dockerfile index 5125e3c3c..25e9a9e37 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,5 +1,5 @@ # syntax=docker/dockerfile:1.8 -ARG RUST_VERSION=1.78 +ARG RUST_VERSION=1.80 ARG CARGO_BUILD_FEATURES=default ARG RUST_RELEASE_MODE=debug From 5421e9a3c78a4cf28711d50fbdd107b84a91bd7f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 30 Jul 2024 15:38:17 +0000 Subject: [PATCH 31/69] chore(deps): update dependency prettier to v3.3.3 (#4929) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 31ec952c1..d6b02d0a6 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: version: 9.5.0 eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.1.3(eslint@9.5.0)(prettier@3.3.2) + version: 5.1.3(eslint@9.5.0)(prettier@3.3.3) jest: specifier: ^29.5.0 version: 29.7.0(@types/node@20.14.5) @@ -37,7 +37,7 @@ importers: version: 0.19.5-alpha.1 prettier: specifier: ^3.2.5 - version: 3.3.2 + version: 3.3.3 ts-jest: specifier: ^29.1.0 version: 29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.5))(typescript@5.4.5) @@ -1404,8 +1404,8 @@ packages: resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} engines: {node: '>=6.0.0'} - prettier@3.3.2: - resolution: {integrity: sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==} + prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} engines: {node: '>=14'} hasBin: true @@ -2596,10 +2596,10 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-prettier@5.1.3(eslint@9.5.0)(prettier@3.3.2): + eslint-plugin-prettier@5.1.3(eslint@9.5.0)(prettier@3.3.3): dependencies: eslint: 9.5.0 - prettier: 3.3.2 + prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.8.8 @@ -3377,7 +3377,7 @@ snapshots: dependencies: fast-diff: 1.3.0 - prettier@3.3.2: {} + prettier@3.3.3: {} pretty-format@29.7.0: dependencies: From 0a6186d7aaeb48a8be1862ca2a6100901bed97ac Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 31 Jul 2024 18:54:44 -0400 Subject: [PATCH 32/69] Fixing apt-key deprecation, and using apt-get. (#4931) * Fixing apt-key deprecation, and using apt-get. * Try 2 * Try 3 * Try 4 * Try 5 * Try 6 * Try 7 * Try 8 * Try 9 * Try 10 * Try 11 * Try 12 * Try 13 * Try 14 * Try 15 * Try 16 * Try 17 --- .woodpecker.yml | 30 ++++++++++------------------ docker/federation/docker-compose.yml | 2 +- 2 files changed, 11 insertions(+), 21 deletions(-) diff --git a/.woodpecker.yml b/.woodpecker.yml index f67c1e44c..50403711e 100644 --- a/.woodpecker.yml +++ b/.woodpecker.yml @@ -5,6 +5,11 @@ variables: - &rust_image "rust:1.80" - &rust_nightly_image "rustlang/rust:nightly" - &install_pnpm "corepack enable pnpm" + - &install_binstall "wget -O- https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz | tar -xvz -C /usr/local/cargo/bin" + - install_diesel_cli: &install_diesel_cli + - apt-get update && apt-get install -y postgresql-client + - cargo install diesel_cli --no-default-features --features postgres + - export PATH="$CARGO_HOME/bin:$PATH" - &slow_check_paths - event: pull_request path: @@ -25,17 +30,6 @@ variables: "diesel.toml", ".gitmodules", ] - - install_binstall: &install_binstall - - wget https://github.com/cargo-bins/cargo-binstall/releases/latest/download/cargo-binstall-x86_64-unknown-linux-musl.tgz - - tar -xvf cargo-binstall-x86_64-unknown-linux-musl.tgz - - cp cargo-binstall /usr/local/cargo/bin - - install_diesel_cli: &install_diesel_cli - - apt update && apt install -y lsb-release build-essential - - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' - - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - - - apt update && apt install -y postgresql-client-16 - - cargo install diesel_cli --no-default-features --features postgres - - export PATH="$CARGO_HOME/bin:$PATH" steps: prepare_repo: @@ -82,7 +76,7 @@ steps: cargo_machete: image: *rust_nightly_image commands: - - <<: *install_binstall + - *install_binstall - cargo binstall -y cargo-machete - cargo machete when: @@ -204,11 +198,6 @@ steps: - <<: *install_diesel_cli # Run all migrations - diesel migration run - # Dump schema to before.sqldump (PostgreSQL apt repo is used to prevent pg_dump version mismatch error) - - apt update && apt install -y lsb-release - - sh -c 'echo "deb https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' - - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add - - - apt update && apt install -y postgresql-client-16 - psql -c "DROP SCHEMA IF EXISTS r CASCADE;" - pg_dump --no-owner --no-privileges --no-table-access-method --schema-only --no-sync -f before.sqldump # Make sure that the newest migration is revertable without the `r` schema @@ -232,7 +221,7 @@ steps: DO_WRITE_HOSTS_FILE: "1" commands: - *install_pnpm - - apt update && apt install -y bash curl postgresql-client + - apt-get update && apt-get install -y bash curl postgresql-client - bash api_tests/prepare-drone-federation-test.sh - cd api_tests/ - pnpm i @@ -279,7 +268,7 @@ steps: publish_to_crates_io: image: *rust_image commands: - - <<: *install_binstall + - *install_binstall # Install cargo-workspaces - cargo binstall -y cargo-workspaces - cp -r migrations crates/db_schema/ @@ -307,7 +296,8 @@ steps: services: database: - image: pgautoupgrade/pgautoupgrade:16-alpine + # 15-alpine image necessary because of diesel tests + image: pgautoupgrade/pgautoupgrade:15-alpine environment: POSTGRES_USER: lemmy POSTGRES_PASSWORD: password diff --git a/docker/federation/docker-compose.yml b/docker/federation/docker-compose.yml index 2befc78c5..090ad71a8 100644 --- a/docker/federation/docker-compose.yml +++ b/docker/federation/docker-compose.yml @@ -20,7 +20,7 @@ x-lemmy-default: &lemmy-default restart: always x-postgres-default: &postgres-default - image: pgautoupgrade/pgautoupgrade:16-alpine + image: pgautoupgrade/pgautoupgrade:15-alpine environment: - POSTGRES_USER=lemmy - POSTGRES_PASSWORD=password From cbb37fa2f1d674d97391ae484c70515a14f3cdc7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 19:28:17 -0400 Subject: [PATCH 33/69] chore(deps): update dependency @types/node to v20.14.13 (#4928) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 68 ++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index d6b02d0a6..08726640e 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 29.5.12 '@types/node': specifier: ^20.12.4 - version: 20.14.5 + version: 20.14.13 '@typescript-eslint/eslint-plugin': specifier: ^7.5.0 version: 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) @@ -31,7 +31,7 @@ importers: version: 5.1.3(eslint@9.5.0)(prettier@3.3.3) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@20.14.5) + version: 29.7.0(@types/node@20.14.13) lemmy-js-client: specifier: 0.19.5-alpha.1 version: 0.19.5-alpha.1 @@ -40,7 +40,7 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.5))(typescript@5.4.5) + version: 29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5) typescript: specifier: ^5.4.4 version: 5.4.5 @@ -407,8 +407,8 @@ packages: '@types/jest@29.5.12': resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} - '@types/node@20.14.5': - resolution: {integrity: sha512-aoRR+fJkZT2l0aGOJhuA8frnCSoNX6W7U2mpNq63+BxBIj5BQFt8rHy627kijCmm63ijdSdwvGgpUsU6MBsZZA==} + '@types/node@20.14.13': + resolution: {integrity: sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -1938,7 +1938,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -1951,14 +1951,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.5) + jest-config: 29.7.0(@types/node@20.14.13) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -1983,7 +1983,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -2001,7 +2001,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.5 + '@types/node': 20.14.13 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2023,7 +2023,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.22 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2093,7 +2093,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.5 + '@types/node': 20.14.13 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -2161,7 +2161,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.5 + '@types/node': 20.14.13 '@types/istanbul-lib-coverage@2.0.6': {} @@ -2178,7 +2178,7 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/node@20.14.5': + '@types/node@20.14.13': dependencies: undici-types: 5.26.5 @@ -2533,13 +2533,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@20.14.5): + create-jest@29.7.0(@types/node@20.14.13): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.5) + jest-config: 29.7.0(@types/node@20.14.13) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -2905,7 +2905,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -2925,16 +2925,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.5): + jest-cli@29.7.0(@types/node@20.14.13): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.5) + create-jest: 29.7.0(@types/node@20.14.13) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.5) + jest-config: 29.7.0(@types/node@20.14.13) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -2944,7 +2944,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.5): + jest-config@29.7.0(@types/node@20.14.13): dependencies: '@babel/core': 7.23.9 '@jest/test-sequencer': 29.7.0 @@ -2969,7 +2969,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.5 + '@types/node': 20.14.13 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -2998,7 +2998,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -3008,7 +3008,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.5 + '@types/node': 20.14.13 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -3047,7 +3047,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -3082,7 +3082,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3110,7 +3110,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3156,7 +3156,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -3175,7 +3175,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.5 + '@types/node': 20.14.13 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3184,17 +3184,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.14.5 + '@types/node': 20.14.13 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.5): + jest@29.7.0(@types/node@20.14.13): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.5) + jest-cli: 29.7.0(@types/node@20.14.13) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3511,11 +3511,11 @@ snapshots: dependencies: typescript: 5.4.5 - ts-jest@29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.5))(typescript@5.4.5): + ts-jest@29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.5) + jest: 29.7.0(@types/node@20.14.13) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 From 60a7829638a4158a58384f3fd36999a5f9fbeab2 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Wed, 31 Jul 2024 20:28:41 -0400 Subject: [PATCH 34/69] Adding deny unimplemented to clippy lints. (#4922) * Adding deny unimplemented to clippy lints. - Context: #4782 * Update crates/apub/src/fetcher/site_or_community_or_user.rs Thanks, I like that better. Co-authored-by: dullbananas * Update crates/apub/src/fetcher/search.rs Co-authored-by: dullbananas * Running fmt. * Adding debug_assert(false) * Removing some commands. * Format. * Remove todo. --------- Co-authored-by: dullbananas --- Cargo.toml | 1 + crates/apub/src/activities/block/mod.rs | 15 ++++--- crates/apub/src/activities/deletion/delete.rs | 5 ++- .../src/activities/deletion/undo_delete.rs | 5 ++- crates/apub/src/activity_lists.rs | 4 +- crates/apub/src/fetcher/post_or_comment.rs | 7 ++- crates/apub/src/fetcher/search.rs | 13 +++++- .../src/fetcher/site_or_community_or_user.rs | 43 ++++++++++++++----- crates/apub/src/fetcher/user_or_community.rs | 12 ++++-- crates/apub/src/objects/instance.rs | 2 +- crates/apub/src/objects/private_message.rs | 2 +- crates/apub/src/protocol/objects/page.rs | 6 ++- crates/db_schema/src/impls/comment.rs | 2 +- crates/db_schema/src/impls/person.rs | 5 ++- .../src/impls/private_message_report.rs | 2 +- crates/db_schema/src/impls/site.rs | 2 +- crates/utils/src/error.rs | 1 + 17 files changed, 90 insertions(+), 37 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 5c4ea3819..42cd00dea 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -86,6 +86,7 @@ suspicious = { level = "deny", priority = -1 } uninlined_format_args = "allow" unused_self = "deny" unwrap_used = "deny" +unimplemented = "deny" [workspace.dependencies] lemmy_api = { version = "=0.19.5", path = "./crates/api" } diff --git a/crates/apub/src/activities/block/mod.rs b/crates/apub/src/activities/block/mod.rs index ced50e2de..d42b62369 100644 --- a/crates/apub/src/activities/block/mod.rs +++ b/crates/apub/src/activities/block/mod.rs @@ -38,7 +38,6 @@ pub enum SiteOrCommunity { Site(ApubSite), Community(ApubCommunity), } - #[derive(Deserialize)] #[serde(untagged)] pub enum InstanceOrGroup { @@ -74,12 +73,18 @@ impl Object for SiteOrCommunity { }) } - async fn delete(self, _data: &Data) -> LemmyResult<()> { - unimplemented!() + async fn delete(self, data: &Data) -> LemmyResult<()> { + match self { + SiteOrCommunity::Site(i) => i.delete(data).await, + SiteOrCommunity::Community(c) => c.delete(data).await, + } } - async fn into_json(self, _data: &Data) -> LemmyResult { - unimplemented!() + async fn into_json(self, data: &Data) -> LemmyResult { + Ok(match self { + SiteOrCommunity::Site(i) => InstanceOrGroup::Instance(i.into_json(data).await?), + SiteOrCommunity::Community(c) => InstanceOrGroup::Group(c.into_json(data).await?), + }) } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/activities/deletion/delete.rs b/crates/apub/src/activities/deletion/delete.rs index cecc051b4..d203aacf2 100644 --- a/crates/apub/src/activities/deletion/delete.rs +++ b/crates/apub/src/activities/deletion/delete.rs @@ -175,8 +175,9 @@ pub(in crate::activities) async fn receive_remove_action( ) .await?; } - DeletableObjects::PrivateMessage(_) => unimplemented!(), - DeletableObjects::Person { .. } => unimplemented!(), + // TODO these need to be implemented yet, for now, return errors + DeletableObjects::PrivateMessage(_) => Err(LemmyErrorType::CouldntFindPrivateMessage)?, + DeletableObjects::Person(_) => Err(LemmyErrorType::CouldntFindPerson)?, } Ok(()) } diff --git a/crates/apub/src/activities/deletion/undo_delete.rs b/crates/apub/src/activities/deletion/undo_delete.rs index 4f0fad670..b50580852 100644 --- a/crates/apub/src/activities/deletion/undo_delete.rs +++ b/crates/apub/src/activities/deletion/undo_delete.rs @@ -155,8 +155,9 @@ impl UndoDelete { ) .await?; } - DeletableObjects::PrivateMessage(_) => unimplemented!(), - DeletableObjects::Person { .. } => unimplemented!(), + // TODO these need to be implemented yet, for now, return errors + DeletableObjects::PrivateMessage(_) => Err(LemmyErrorType::CouldntFindPrivateMessage)?, + DeletableObjects::Person(_) => Err(LemmyErrorType::CouldntFindPerson)?, } Ok(()) } diff --git a/crates/apub/src/activity_lists.rs b/crates/apub/src/activity_lists.rs index 3aeb7e45e..2d1fac449 100644 --- a/crates/apub/src/activity_lists.rs +++ b/crates/apub/src/activity_lists.rs @@ -26,7 +26,7 @@ use crate::{ }; use activitypub_federation::{config::Data, traits::ActivityHandler}; use lemmy_api_common::context::LemmyContext; -use lemmy_utils::error::LemmyResult; +use lemmy_utils::{error::LemmyResult, LemmyErrorType}; use serde::{Deserialize, Serialize}; use url::Url; @@ -117,7 +117,7 @@ impl InCommunity for AnnouncableActivities { CollectionRemove(a) => a.community(context).await, LockPost(a) => a.community(context).await, UndoLockPost(a) => a.community(context).await, - Page(_) => unimplemented!(), + Page(_) => Err(LemmyErrorType::CouldntFindPost.into()), } } } diff --git a/crates/apub/src/fetcher/post_or_comment.rs b/crates/apub/src/fetcher/post_or_comment.rs index 083369b9d..e352e1257 100644 --- a/crates/apub/src/fetcher/post_or_comment.rs +++ b/crates/apub/src/fetcher/post_or_comment.rs @@ -61,8 +61,11 @@ impl Object for PostOrComment { } } - async fn into_json(self, _data: &Data) -> LemmyResult { - unimplemented!() + async fn into_json(self, data: &Data) -> LemmyResult { + Ok(match self { + PostOrComment::Post(p) => PageOrNote::Page(Box::new(p.into_json(data).await?)), + PostOrComment::Comment(c) => PageOrNote::Note(c.into_json(data).await?), + }) } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/fetcher/search.rs b/crates/apub/src/fetcher/search.rs index 8c533ba88..76c284820 100644 --- a/crates/apub/src/fetcher/search.rs +++ b/crates/apub/src/fetcher/search.rs @@ -118,8 +118,17 @@ impl Object for SearchableObjects { } } - async fn into_json(self, _data: &Data) -> LemmyResult { - unimplemented!() + async fn into_json(self, data: &Data) -> LemmyResult { + Ok(match self { + SearchableObjects::Post(p) => SearchableKinds::Page(Box::new(p.into_json(data).await?)), + SearchableObjects::Comment(c) => SearchableKinds::Note(c.into_json(data).await?), + SearchableObjects::PersonOrCommunity(pc) => { + SearchableKinds::PersonOrGroup(Box::new(match *pc { + UserOrCommunity::User(p) => PersonOrGroup::Person(p.into_json(data).await?), + UserOrCommunity::Community(c) => PersonOrGroup::Group(c.into_json(data).await?), + })) + } + }) } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/fetcher/site_or_community_or_user.rs b/crates/apub/src/fetcher/site_or_community_or_user.rs index 30b5fd568..c6a1bb17e 100644 --- a/crates/apub/src/fetcher/site_or_community_or_user.rs +++ b/crates/apub/src/fetcher/site_or_community_or_user.rs @@ -1,6 +1,6 @@ use crate::{ fetcher::user_or_community::{PersonOrGroup, UserOrCommunity}, - objects::instance::ApubSite, + objects::{community::ApubCommunity, instance::ApubSite, person::ApubPerson}, protocol::objects::instance::Instance, }; use activitypub_federation::{ @@ -41,11 +41,14 @@ impl Object for SiteOrCommunityOrUser { } #[tracing::instrument(skip_all)] - async fn read_from_id( - _object_id: Url, - _data: &Data, - ) -> LemmyResult> { - unimplemented!(); + async fn read_from_id(object_id: Url, data: &Data) -> LemmyResult> { + let site = ApubSite::read_from_id(object_id.clone(), data).await?; + Ok(match site { + Some(o) => Some(SiteOrCommunityOrUser::Site(o)), + None => UserOrCommunity::read_from_id(object_id, data) + .await? + .map(SiteOrCommunityOrUser::UserOrCommunity), + }) } #[tracing::instrument(skip_all)] @@ -56,8 +59,13 @@ impl Object for SiteOrCommunityOrUser { } } - async fn into_json(self, _data: &Data) -> LemmyResult { - unimplemented!() + async fn into_json(self, data: &Data) -> LemmyResult { + Ok(match self { + SiteOrCommunityOrUser::Site(p) => SiteOrPersonOrGroup::Instance(p.into_json(data).await?), + SiteOrCommunityOrUser::UserOrCommunity(p) => { + SiteOrPersonOrGroup::PersonOrGroup(p.into_json(data).await?) + } + }) } #[tracing::instrument(skip_all)] @@ -75,8 +83,18 @@ impl Object for SiteOrCommunityOrUser { } #[tracing::instrument(skip_all)] - async fn from_json(_apub: Self::Kind, _data: &Data) -> LemmyResult { - unimplemented!(); + async fn from_json(apub: Self::Kind, data: &Data) -> LemmyResult { + Ok(match apub { + SiteOrPersonOrGroup::Instance(a) => { + SiteOrCommunityOrUser::Site(ApubSite::from_json(a, data).await?) + } + SiteOrPersonOrGroup::PersonOrGroup(a) => SiteOrCommunityOrUser::UserOrCommunity(match a { + PersonOrGroup::Person(p) => UserOrCommunity::User(ApubPerson::from_json(p, data).await?), + PersonOrGroup::Group(g) => { + UserOrCommunity::Community(ApubCommunity::from_json(g, data).await?) + } + }), + }) } } @@ -103,6 +121,9 @@ impl Actor for SiteOrCommunityOrUser { } fn inbox(&self) -> Url { - unimplemented!() + match self { + SiteOrCommunityOrUser::Site(u) => u.inbox(), + SiteOrCommunityOrUser::UserOrCommunity(c) => c.inbox(), + } } } diff --git a/crates/apub/src/fetcher/user_or_community.rs b/crates/apub/src/fetcher/user_or_community.rs index d29cbb6b0..129af8803 100644 --- a/crates/apub/src/fetcher/user_or_community.rs +++ b/crates/apub/src/fetcher/user_or_community.rs @@ -65,8 +65,11 @@ impl Object for UserOrCommunity { } } - async fn into_json(self, _data: &Data) -> LemmyResult { - unimplemented!() + async fn into_json(self, data: &Data) -> LemmyResult { + Ok(match self { + UserOrCommunity::User(p) => PersonOrGroup::Person(p.into_json(data).await?), + UserOrCommunity::Community(p) => PersonOrGroup::Group(p.into_json(data).await?), + }) } #[tracing::instrument(skip_all)] @@ -115,7 +118,10 @@ impl Actor for UserOrCommunity { } fn inbox(&self) -> Url { - unimplemented!() + match self { + UserOrCommunity::User(p) => p.inbox(), + UserOrCommunity::Community(p) => p.inbox(), + } } } diff --git a/crates/apub/src/objects/instance.rs b/crates/apub/src/objects/instance.rs index 6f0a7328d..c67a223e0 100644 --- a/crates/apub/src/objects/instance.rs +++ b/crates/apub/src/objects/instance.rs @@ -88,7 +88,7 @@ impl Object for ApubSite { } async fn delete(self, _data: &Data) -> LemmyResult<()> { - unimplemented!() + Err(LemmyErrorType::CantDeleteSite.into()) } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/objects/private_message.rs b/crates/apub/src/objects/private_message.rs index 35f2fe418..fc9697391 100644 --- a/crates/apub/src/objects/private_message.rs +++ b/crates/apub/src/objects/private_message.rs @@ -73,7 +73,7 @@ impl Object for ApubPrivateMessage { async fn delete(self, _context: &Data) -> LemmyResult<()> { // do nothing, because pm can't be fetched over http - unimplemented!() + Err(LemmyErrorType::CouldntFindPrivateMessage.into()) } #[tracing::instrument(skip_all)] diff --git a/crates/apub/src/protocol/objects/page.rs b/crates/apub/src/protocol/objects/page.rs index 6075b14a1..9c37c88c3 100644 --- a/crates/apub/src/protocol/objects/page.rs +++ b/crates/apub/src/protocol/objects/page.rs @@ -193,10 +193,12 @@ impl ActivityHandler for Page { type DataType = LemmyContext; type Error = LemmyError; fn id(&self) -> &Url { - unimplemented!() + self.id.inner() } + fn actor(&self) -> &Url { - unimplemented!() + debug_assert!(false); + self.id.inner() } async fn verify(&self, data: &Data) -> LemmyResult<()> { ApubPost::verify(self, self.id.inner(), data).await diff --git a/crates/db_schema/src/impls/comment.rs b/crates/db_schema/src/impls/comment.rs index aa7b418fe..977bc9083 100644 --- a/crates/db_schema/src/impls/comment.rs +++ b/crates/db_schema/src/impls/comment.rs @@ -117,7 +117,7 @@ impl Crud for Comment { type UpdateForm = CommentUpdateForm; type IdType = CommentId; - /// This is unimplemented, use [[Comment::create]] + /// Use [[Comment::create]] async fn create(pool: &mut DbPool<'_>, comment_form: &Self::InsertForm) -> Result { debug_assert!(false); Comment::create(pool, comment_form, None).await diff --git a/crates/db_schema/src/impls/person.rs b/crates/db_schema/src/impls/person.rs index 89c108f8c..f2909218c 100644 --- a/crates/db_schema/src/impls/person.rs +++ b/crates/db_schema/src/impls/person.rs @@ -191,9 +191,12 @@ impl Followable for PersonFollower { .get_result::(conn) .await } + + /// Currently no user following async fn follow_accepted(_: &mut DbPool<'_>, _: CommunityId, _: PersonId) -> Result { - unimplemented!() + Err(Error::NotFound) } + async fn unfollow(pool: &mut DbPool<'_>, form: &PersonFollowerForm) -> Result { let conn = &mut get_conn(pool).await?; diesel::delete(person_follower::table.find((form.follower_id, form.person_id))) diff --git a/crates/db_schema/src/impls/private_message_report.rs b/crates/db_schema/src/impls/private_message_report.rs index b5d8fd039..0d5876659 100644 --- a/crates/db_schema/src/impls/private_message_report.rs +++ b/crates/db_schema/src/impls/private_message_report.rs @@ -52,7 +52,7 @@ impl Reportable for PrivateMessageReport { _pm_id_: PrivateMessageId, _by_resolver_id: PersonId, ) -> Result { - unimplemented!() + Err(Error::NotFound) } async fn unresolve( diff --git a/crates/db_schema/src/impls/site.rs b/crates/db_schema/src/impls/site.rs index a371f9e07..9dbd2401d 100644 --- a/crates/db_schema/src/impls/site.rs +++ b/crates/db_schema/src/impls/site.rs @@ -20,7 +20,7 @@ impl Crud for Site { /// Use SiteView::read_local, or Site::read_from_apub_id instead async fn read(_pool: &mut DbPool<'_>, _site_id: SiteId) -> Result, Error> { - unimplemented!() + Err(Error::NotFound) } async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result { diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index 896539057..542888612 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -179,6 +179,7 @@ pub enum LemmyErrorType { UrlWithoutDomain, InboxTimeout, Unknown(String), + CantDeleteSite, } cfg_if! { From c6db2ad9b70ccb74f32bf063805a2c4a5c4cbf58 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 31 Jul 2024 21:46:20 -0400 Subject: [PATCH 35/69] chore(deps): update rust crate serde_json to v1.0.121 (#4933) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index efe905559..0156958b3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5281,12 +5281,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.120" +version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e0d21c9a8cae1235ad58a00c11cb40d4b1e5c784f1ef2c537876ed6ffd8b7c5" +checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ "indexmap 2.2.6", "itoa", + "memchr", "ryu", "serde", ] From 0bd0c0f11b3c8322d738c1d94ea8fee4ce60a5af Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 11:38:06 +0000 Subject: [PATCH 36/69] chore(deps): update rust crate clap to v4.5.13 (#4932) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0156958b3..702945fbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -970,9 +970,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "35723e6a11662c2afb578bcf0b88bf6ea8e21282a953428f240574fcc3a2b5b3" +checksum = "0fbb260a053428790f3de475e304ff84cdbc4face759ea7a3e64c1edd938a7fc" dependencies = [ "clap_builder", "clap_derive", @@ -980,9 +980,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49eb96cbfa7cfa35017b7cd548c75b14c3118c98b423041d70562665e07fb0fa" +checksum = "64b17d7ea74e9f833c7dbf2cbe4fb12ff26783eda4782a8975b72f895c9b4d99" dependencies = [ "anstream", "anstyle", @@ -992,9 +992,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.11" +version = "4.5.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d029b67f89d30bbb547c89fd5161293c0aec155fc691d7924b64550662db93e" +checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" dependencies = [ "heck 0.5.0", "proc-macro2", @@ -3151,7 +3151,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.52.6", + "windows-targets 0.48.5", ] [[package]] From 6c11c013b0a70fec255e7ac2d6fd4a9585351af3 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 1 Aug 2024 08:29:22 -0400 Subject: [PATCH 37/69] Version 0.19.6-beta.2 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 702945fbe..a158da9a0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2743,7 +2743,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2772,7 +2772,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2809,7 +2809,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "accept-language", "activitypub_federation", @@ -2831,7 +2831,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-web", @@ -2868,7 +2868,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "anyhow", "clap", @@ -2883,7 +2883,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "anyhow", @@ -2922,7 +2922,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "actix-web", "chrono", @@ -2944,7 +2944,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "chrono", "diesel", @@ -2964,7 +2964,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "diesel", "diesel-async", @@ -2976,7 +2976,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-web", @@ -3007,7 +3007,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-web", @@ -3031,7 +3031,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "activitypub_federation", "actix-cors", @@ -3075,7 +3075,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.5" +version = "0.19.6-beta.2" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 42cd00dea..b91c59dc4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.5" +version = "0.19.6-beta.2" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.5", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.5", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.5", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.5", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.5", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.5", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.5", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.5", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.5", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.5", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.5", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.2", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.2", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.2", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.2", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.2", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.2", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.2", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.2", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.2", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.2", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.2", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index ee2cffac8..088a27703 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit ee2cffac809ad466644f061ad79ac577b6c2e4fd +Subproject commit 088a27703ffa65e069dfbf341ee9bd44ec4c45c5 From 4e48054b173dce463d01790ba01b226233615cfe Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:50:52 +0000 Subject: [PATCH 38/69] chore(deps): update rust crate tokio to v1.39.2 (#4935) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a158da9a0..1d8bda827 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5915,9 +5915,9 @@ dependencies = [ [[package]] name = "tokio" -version = "1.39.1" +version = "1.39.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d040ac2b29ab03b09d4129c2f5bbd012a3ac2f79d38ff506a4bf8dd34b0eac8a" +checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1" dependencies = [ "backtrace", "bytes", From fa836bb35a22c58f0a9ab15778e0262cc78d9817 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:51:26 -0400 Subject: [PATCH 39/69] chore(deps): update dependency ts-jest to v29.2.4 (#4941) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 65 +++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 08726640e..2ad1778d5 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -40,7 +40,7 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5) + version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5) typescript: specifier: ^5.4.4 version: 5.4.5 @@ -582,6 +582,9 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -760,6 +763,11 @@ packages: download-file-sync@1.0.4: resolution: {integrity: sha512-vH92qNH508jZZA12HQNq/aiMDfagr4JvjFiI17Bi8oYjsxwv5ZVIi7iHkYmUXxOQUr90tcVX+8EPePjAqG1Y0w==} + ejs@3.1.10: + resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} + engines: {node: '>=0.10.0'} + hasBin: true + electron-to-chromium@1.4.648: resolution: {integrity: sha512-EmFMarXeqJp9cUKu/QEciEApn0S/xRcpZWuAm32U7NgoZCimjsilKXHRO9saeEW55eHZagIDg6XTUOv32w9pjg==} @@ -883,6 +891,9 @@ packages: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} + filelist@1.0.4: + resolution: {integrity: sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==} + fill-range@7.0.1: resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} engines: {node: '>=8'} @@ -1067,6 +1078,11 @@ packages: resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} engines: {node: '>=8'} + jake@10.9.2: + resolution: {integrity: sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==} + engines: {node: '>=10'} + hasBin: true + jest-changed-files@29.7.0: resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -1299,6 +1315,10 @@ packages: minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + minimatch@5.1.6: + resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} + engines: {node: '>=10'} + minimatch@9.0.4: resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} engines: {node: '>=16 || 14 >=14.17'} @@ -1470,6 +1490,11 @@ packages: engines: {node: '>=10'} hasBin: true + semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -1570,8 +1595,8 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-jest@29.1.5: - resolution: {integrity: sha512-UuClSYxM7byvvYfyWdFI+/2UxMmwNyJb0NPkZPQE2hew3RurV7l7zURgOHAd/1I1ZdPpe3GUsXNXAcN8TFKSIg==} + ts-jest@29.2.4: + resolution: {integrity: sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2298,7 +2323,7 @@ snapshots: globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 - semver: 7.6.2 + semver: 7.6.3 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 @@ -2394,6 +2419,8 @@ snapshots: array-union@2.1.0: {} + async@3.2.5: {} + babel-jest@29.7.0(@babel/core@7.23.9): dependencies: '@babel/core': 7.23.9 @@ -2578,6 +2605,10 @@ snapshots: download-file-sync@1.0.4: {} + ejs@3.1.10: + dependencies: + jake: 10.9.2 + electron-to-chromium@1.4.648: {} emittery@0.13.1: {} @@ -2721,6 +2752,10 @@ snapshots: dependencies: flat-cache: 4.0.1 + filelist@1.0.4: + dependencies: + minimatch: 5.1.6 + fill-range@7.0.1: dependencies: to-regex-range: 5.0.1 @@ -2870,7 +2905,7 @@ snapshots: '@babel/parser': 7.23.9 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.2 - semver: 7.6.2 + semver: 7.6.3 transitivePeerDependencies: - supports-color @@ -2893,6 +2928,13 @@ snapshots: html-escaper: 2.0.2 istanbul-lib-report: 3.0.1 + jake@10.9.2: + dependencies: + async: 3.2.5 + chalk: 4.1.2 + filelist: 1.0.4 + minimatch: 3.1.2 + jest-changed-files@29.7.0: dependencies: execa: 5.1.1 @@ -3259,7 +3301,7 @@ snapshots: make-dir@4.0.0: dependencies: - semver: 7.6.2 + semver: 7.6.3 make-error@1.3.6: {} @@ -3287,6 +3329,10 @@ snapshots: dependencies: brace-expansion: 1.1.11 + minimatch@5.1.6: + dependencies: + brace-expansion: 2.0.1 + minimatch@9.0.4: dependencies: brace-expansion: 2.0.1 @@ -3426,6 +3472,8 @@ snapshots: semver@7.6.2: {} + semver@7.6.3: {} + shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 @@ -3511,16 +3559,17 @@ snapshots: dependencies: typescript: 5.4.5 - ts-jest@29.1.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5): + ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5): dependencies: bs-logger: 0.2.6 + ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 jest: 29.7.0(@types/node@20.14.13) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 make-error: 1.3.6 - semver: 7.6.2 + semver: 7.6.3 typescript: 5.4.5 yargs-parser: 21.1.1 optionalDependencies: From 4e7e92da944769c82f09d9c81e94d4f0f6a513fd Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:51:37 -0400 Subject: [PATCH 40/69] chore(deps): update dependency eslint-plugin-prettier to v5.2.1 (#4940) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 2ad1778d5..f2ca00239 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -28,7 +28,7 @@ importers: version: 9.5.0 eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.1.3(eslint@9.5.0)(prettier@3.3.3) + version: 5.2.1(eslint@9.5.0)(prettier@3.3.3) jest: specifier: ^29.5.0 version: 29.7.0(@types/node@20.14.13) @@ -797,8 +797,8 @@ packages: resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} engines: {node: '>=10'} - eslint-plugin-prettier@5.1.3: - resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + eslint-plugin-prettier@5.2.1: + resolution: {integrity: sha512-gH3iR3g4JfF+yYPaJYkN7jEl9QbweL/YfkoRlNnuIEHEz1vHVlCmWOS+eGGiRuzHQXdJFCOTxRgvju9b8VUmrw==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: '@types/eslint': '>=8.0.0' @@ -1567,8 +1567,8 @@ packages: resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} engines: {node: '>= 0.4'} - synckit@0.8.8: - resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + synckit@0.9.1: + resolution: {integrity: sha512-7gr8p9TQP6RAHusBOSLs46F4564ZrjV8xFmw5zCmgmhGUcw2hxsShhJ6CEiHQMgPDwAQ1fWHPM0ypc4RMAig4A==} engines: {node: ^14.18.0 || >=16.0.0} test-exclude@6.0.0: @@ -1619,8 +1619,8 @@ packages: esbuild: optional: true - tslib@2.6.2: - resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + tslib@2.6.3: + resolution: {integrity: sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==} type-check@0.4.0: resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} @@ -2627,12 +2627,12 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-prettier@5.1.3(eslint@9.5.0)(prettier@3.3.3): + eslint-plugin-prettier@5.2.1(eslint@9.5.0)(prettier@3.3.3): dependencies: eslint: 9.5.0 prettier: 3.3.3 prettier-linter-helpers: 1.0.0 - synckit: 0.8.8 + synckit: 0.9.1 eslint-scope@8.0.1: dependencies: @@ -3534,10 +3534,10 @@ snapshots: supports-preserve-symlinks-flag@1.0.0: {} - synckit@0.8.8: + synckit@0.9.1: dependencies: '@pkgr/core': 0.1.1 - tslib: 2.6.2 + tslib: 2.6.3 test-exclude@6.0.0: dependencies: @@ -3578,7 +3578,7 @@ snapshots: '@jest/types': 29.6.3 babel-jest: 29.7.0(@babel/core@7.23.9) - tslib@2.6.2: {} + tslib@2.6.3: {} type-check@0.4.0: dependencies: From 75d8d704e7f0dd58b67aef8180e3893b6a4dca28 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:52:24 -0400 Subject: [PATCH 41/69] chore(deps): update pnpm to v9.6.0 (#4939) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/package.json b/api_tests/package.json index 6a14bded7..57b198237 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -6,7 +6,7 @@ "repository": "https://github.com/LemmyNet/lemmy", "author": "Dessalines", "license": "AGPL-3.0", - "packageManager": "pnpm@9.4.0", + "packageManager": "pnpm@9.6.0", "scripts": { "lint": "tsc --noEmit && eslint --report-unused-disable-directives && prettier --check 'src/**/*.ts'", "fix": "prettier --write src && eslint --fix src", From 23184734560b1bfbf2b7119b646b97ae96ece7ee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:52:40 -0400 Subject: [PATCH 42/69] fix(deps): update rust crate console-subscriber to 0.4.0 (#4944) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 167 ++++++++++++++++++++++++++++++++++++++++++++++------- Cargo.toml | 2 +- 2 files changed, 146 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 1d8bda827..72286976d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -612,7 +612,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", - "axum-core", + "axum-core 0.3.4", "bitflags 1.3.2", "bytes", "futures-util", @@ -633,6 +633,33 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a6c9af12842a67734c9a2e355436e5d03b22383ed60cf13cd0c18fbfe3dcbcf" +dependencies = [ + "async-trait", + "axum-core 0.4.3", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "itoa", + "matchit 0.7.3", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper 1.0.1", + "tower", + "tower-layer", + "tower-service", +] + [[package]] name = "axum-core" version = "0.3.4" @@ -650,6 +677,26 @@ dependencies = [ "tower-service", ] +[[package]] +name = "axum-core" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a15c63fd72d41492dc4f497196f5da1fb04fb7529e631d73630d1b491e47a2e3" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "mime", + "pin-project-lite", + "rustversion", + "sync_wrapper 0.1.2", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -1108,21 +1155,21 @@ checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" dependencies = [ "futures-core", "prost 0.12.6", - "prost-types", + "prost-types 0.12.6", "tonic 0.10.2", "tracing-core", ] [[package]] name = "console-api" -version = "0.7.0" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a257c22cd7e487dd4a13d413beabc512c5052f0bc048db0da6a84c3d8a6142fd" +checksum = "86ed14aa9c9f927213c6e4f3ef75faaad3406134efe84ba2cb7983431d5f0931" dependencies = [ "futures-core", - "prost 0.12.6", - "prost-types", - "tonic 0.11.0", + "prost 0.13.1", + "prost-types 0.13.1", + "tonic 0.12.1", "tracing-core", ] @@ -1138,7 +1185,7 @@ dependencies = [ "futures-task", "hdrhistogram", "humantime", - "prost-types", + "prost-types 0.12.6", "serde", "serde_json", "thread_local", @@ -1152,24 +1199,25 @@ dependencies = [ [[package]] name = "console-subscriber" -version = "0.3.0" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c4cc54bae66f7d9188996404abdf7fdfa23034ef8e43478c8810828abad758" +checksum = "e2e3a111a37f3333946ebf9da370ba5c5577b18eb342ec683eb488dd21980302" dependencies = [ - "console-api 0.7.0", + "console-api 0.8.0", "crossbeam-channel", "crossbeam-utils", "futures-task", "hdrhistogram", "humantime", - "prost 0.12.6", - "prost-types", + "hyper-util", + "prost 0.13.1", + "prost-types 0.13.1", "serde", "serde_json", "thread_local", "tokio", "tokio-stream", - "tonic 0.11.0", + "tonic 0.12.1", "tracing", "tracing-core", "tracing-subscriber", @@ -2455,6 +2503,19 @@ dependencies = [ "tokio-io-timeout", ] +[[package]] +name = "hyper-timeout" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3203a961e5c83b6f5498933e78b6b263e208c197b63e9c6c53cc82ffd3f63793" +dependencies = [ + "hyper 1.4.1", + "hyper-util", + "pin-project-lite", + "tokio", + "tower-service", +] + [[package]] name = "hyper-tls" version = "0.5.0" @@ -3040,7 +3101,7 @@ dependencies = [ "chrono", "clap", "clokwerk", - "console-subscriber 0.3.0", + "console-subscriber 0.4.0", "diesel", "diesel-async", "futures-util", @@ -3151,7 +3212,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4979f22fdb869068da03c9f7528f8297c6fd2606bc3a4affe42e6a823fdb8da4" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] @@ -4423,6 +4484,16 @@ dependencies = [ "prost-derive 0.12.6", ] +[[package]] +name = "prost" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13db3d3fde688c61e2446b4d843bc27a7e8af269a69440c0308021dc92333cc" +dependencies = [ + "bytes", + "prost-derive 0.13.1", +] + [[package]] name = "prost-derive" version = "0.11.9" @@ -4449,6 +4520,19 @@ dependencies = [ "syn 2.0.72", ] +[[package]] +name = "prost-derive" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "18bec9b0adc4eba778b33684b7ba3e7137789434769ee3ce3930463ef904cfca" +dependencies = [ + "anyhow", + "itertools 0.13.0", + "proc-macro2", + "quote", + "syn 2.0.72", +] + [[package]] name = "prost-types" version = "0.12.6" @@ -4458,6 +4542,15 @@ dependencies = [ "prost 0.12.6", ] +[[package]] +name = "prost-types" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cee5168b05f49d4b0ca581206eb14a7b22fafd963efe729ac48eb03266e25cc2" +dependencies = [ + "prost 0.13.1", +] + [[package]] name = "protobuf" version = "2.28.0" @@ -6129,7 +6222,7 @@ checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" dependencies = [ "async-stream", "async-trait", - "axum", + "axum 0.6.20", "base64 0.13.1", "bytes", "futures-core", @@ -6138,7 +6231,7 @@ dependencies = [ "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.11.9", @@ -6161,14 +6254,14 @@ checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" dependencies = [ "async-stream", "async-trait", - "axum", + "axum 0.6.20", "base64 0.21.7", "bytes", "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.12.6", @@ -6188,14 +6281,14 @@ checksum = "76c4eb7a4e9ef9d4763600161f12f5070b92a578e1b634db88a6887844c91a13" dependencies = [ "async-stream", "async-trait", - "axum", + "axum 0.6.20", "base64 0.21.7", "bytes", "h2 0.3.26", "http 0.2.12", "http-body 0.4.6", "hyper 0.14.30", - "hyper-timeout", + "hyper-timeout 0.4.1", "percent-encoding", "pin-project", "prost 0.12.6", @@ -6207,6 +6300,36 @@ dependencies = [ "tracing", ] +[[package]] +name = "tonic" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38659f4a91aba8598d27821589f5db7dddd94601e7a01b1e485a50e5484c7401" +dependencies = [ + "async-stream", + "async-trait", + "axum 0.7.5", + "base64 0.22.1", + "bytes", + "h2 0.4.5", + "http 1.1.0", + "http-body 1.0.1", + "http-body-util", + "hyper 1.4.1", + "hyper-timeout 0.5.1", + "hyper-util", + "percent-encoding", + "pin-project", + "prost 0.13.1", + "socket2", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + [[package]] name = "totp-rs" version = "5.6.0" diff --git a/Cargo.toml b/Cargo.toml index b91c59dc4..d7c652456 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -199,7 +199,7 @@ clokwerk = { workspace = true } serde_json = { workspace = true } tracing-opentelemetry = { workspace = true, optional = true } opentelemetry = { workspace = true, optional = true } -console-subscriber = { version = "0.3.0", optional = true } +console-subscriber = { version = "0.4.0", optional = true } opentelemetry-otlp = { version = "0.12.0", optional = true } pict-rs = { version = "0.5.15", optional = true } rustls = { workspace = true } From 2cab7935dbed2d3c6f387ce6b8fba9742cdd8e10 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 10:53:41 -0400 Subject: [PATCH 43/69] chore(deps): update docker/dockerfile docker tag to v1.9 (#4938) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 25e9a9e37..c7d5c9aa5 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -1,4 +1,4 @@ -# syntax=docker/dockerfile:1.8 +# syntax=docker/dockerfile:1.9 ARG RUST_VERSION=1.80 ARG CARGO_BUILD_FEATURES=default ARG RUST_RELEASE_MODE=debug From 79fddc965fce213a6e1512bad5054324669a6cea Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 16:22:55 +0000 Subject: [PATCH 44/69] chore(deps): update rust crate typed-builder to 0.19.0 (#4949) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 72286976d..4e3c46656 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6603,18 +6603,18 @@ dependencies = [ [[package]] name = "typed-builder" -version = "0.18.2" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77739c880e00693faef3d65ea3aad725f196da38b22fdc7ea6ded6e1ce4d3add" +checksum = "a06fbd5b8de54c5f7c91f6fe4cebb949be2125d7758e630bb58b1d831dbce600" dependencies = [ "typed-builder-macro", ] [[package]] name = "typed-builder-macro" -version = "0.18.2" +version = "0.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f718dfaf347dcb5b983bfc87608144b0bad87970aebcbea5ce44d2a30c08e63" +checksum = "f9534daa9fd3ed0bd911d462a37f172228077e7abf18c18a5f67199d959205f8" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index d7c652456..a336bd200 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -143,7 +143,7 @@ anyhow = { version = "1.0.86", features = [ "backtrace", ] } # backtrace is on by default on nightly, but not stable rust diesel_ltree = "0.3.1" -typed-builder = "0.18.2" +typed-builder = "0.19.0" serial_test = "3.1.1" tokio = { version = "1.38.0", features = ["full"] } regex = "1.10.4" From c0f3dff5cf4ffb3d307aeef5a40fa9c10498d7ff Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:59:40 -0400 Subject: [PATCH 45/69] chore(deps): update rust crate mockall to 0.13.0 (#4946) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 9 ++++----- crates/federate/Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4e3c46656..3dfae09d6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3547,14 +3547,13 @@ checksum = "c9be0862c1b3f26a88803c4a49de6889c10e608b3ee9344e6ef5b45fb37ad3d1" [[package]] name = "mockall" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43766c2b5203b10de348ffe19f7e54564b64f3d6018ff7648d1e2d6d3a0f0a48" +checksum = "d4c28b3fb6d753d28c20e826cd46ee611fda1cf3cde03a443a974043247c065a" dependencies = [ "cfg-if", "downcast", "fragile", - "lazy_static", "mockall_derive", "predicates", "predicates-tree", @@ -3562,9 +3561,9 @@ dependencies = [ [[package]] name = "mockall_derive" -version = "0.12.1" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af7cbce79ec385a1d4f54baa90a76401eb15d9cab93685f62e7e9f942aa00ae2" +checksum = "341014e7f530314e9a1fdbc7400b244efea7122662c96bfa248c31da5bfb2020" dependencies = [ "cfg-if", "proc-macro2", diff --git a/crates/federate/Cargo.toml b/crates/federate/Cargo.toml index 8ffda2dae..6b76dbf97 100644 --- a/crates/federate/Cargo.toml +++ b/crates/federate/Cargo.toml @@ -42,4 +42,4 @@ actix-web.workspace = true tracing-test = "0.2.5" uuid.workspace = true test-context = "0.3.0" -mockall = "0.12.1" +mockall = "0.13.0" From b25f9c3e663c29ed0daa5d79b301f8399ee610d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 13:59:55 -0400 Subject: [PATCH 46/69] chore(deps): update typescript-eslint monorepo to v7.18.0 (#4950) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 283 ++++++++++----------------------------- 1 file changed, 72 insertions(+), 211 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index f2ca00239..65f50a7af 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -16,10 +16,10 @@ importers: version: 20.14.13 '@typescript-eslint/eslint-plugin': specifier: ^7.5.0 - version: 7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) '@typescript-eslint/parser': specifier: ^7.5.0 - version: 7.13.1(eslint@9.5.0)(typescript@5.4.5) + version: 7.18.0(eslint@9.5.0)(typescript@5.4.5) download-file-sync: specifier: ^1.0.4 version: 1.0.4 @@ -46,7 +46,7 @@ importers: version: 5.4.5 typescript-eslint: specifier: ^7.13.0 - version: 7.13.0(eslint@9.5.0)(typescript@5.4.5) + version: 7.18.0(eslint@9.5.0)(typescript@5.4.5) packages: @@ -235,8 +235,8 @@ packages: resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-community/regexpp@4.10.1': - resolution: {integrity: sha512-Zm2NGpWELsQAD1xsJzGQpYfvICSsFkEpU0jxBjfdC6uNEWXcHnfs9hScFWtXVDVl+rBQJGrl4g1vcKIejpH9dA==} + '@eslint-community/regexpp@4.11.0': + resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} '@eslint/config-array@0.16.0': @@ -419,8 +419,8 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.13.0': - resolution: {integrity: sha512-FX1X6AF0w8MdVFLSdqwqN/me2hyhuQg4ykN6ZpVhh1ij/80pTvDKclX1sZB9iqex8SjQfVhwMKs3JtnnMLzG9w==} + '@typescript-eslint/eslint-plugin@7.18.0': + resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: '@typescript-eslint/parser': ^7.0.0 @@ -430,19 +430,8 @@ packages: typescript: optional: true - '@typescript-eslint/eslint-plugin@7.13.1': - resolution: {integrity: sha512-kZqi+WZQaZfPKnsflLJQCz6Ze9FFSMfXrrIOcyargekQxG37ES7DJNpJUE9Q/X5n3yTIP/WPutVNzgknQ7biLg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/parser@7.13.0': - resolution: {integrity: sha512-EjMfl69KOS9awXXe83iRN7oIEXy9yYdqWfqdrFAYAAr6syP8eLEFI7ZE4939antx2mNgPRW/o1ybm2SFYkbTVA==} + '@typescript-eslint/parser@7.18.0': + resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -451,8 +440,12 @@ packages: typescript: optional: true - '@typescript-eslint/parser@7.13.1': - resolution: {integrity: sha512-1ELDPlnLvDQ5ybTSrMhRTFDfOQEOXNM+eP+3HT/Yq7ruWpciQw+Avi73pdEbA4SooCawEWo3dtYbF68gN7Ed1A==} + '@typescript-eslint/scope-manager@7.18.0': + resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} + engines: {node: ^18.18.0 || >=20.0.0} + + '@typescript-eslint/type-utils@7.18.0': + resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -461,44 +454,12 @@ packages: typescript: optional: true - '@typescript-eslint/scope-manager@7.13.0': - resolution: {integrity: sha512-ZrMCe1R6a01T94ilV13egvcnvVJ1pxShkE0+NDjDzH4nvG1wXpwsVI5bZCvE7AEDH1mXEx5tJSVR68bLgG7Dng==} + '@typescript-eslint/types@7.18.0': + resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} engines: {node: ^18.18.0 || >=20.0.0} - '@typescript-eslint/scope-manager@7.13.1': - resolution: {integrity: sha512-adbXNVEs6GmbzaCpymHQ0MB6E4TqoiVbC0iqG3uijR8ZYfpAXMGttouQzF4Oat3P2GxDVIrg7bMI/P65LiQZdg==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/type-utils@7.13.0': - resolution: {integrity: sha512-xMEtMzxq9eRkZy48XuxlBFzpVMDurUAfDu5Rz16GouAtXm0TaAoTFzqWUFPPuQYXI/CDaH/Bgx/fk/84t/Bc9A==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/type-utils@7.13.1': - resolution: {integrity: sha512-aWDbLu1s9bmgPGXSzNCxELu+0+HQOapV/y+60gPXafR8e2g1Bifxzevaa+4L2ytCWm+CHqpELq4CSoN9ELiwCg==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@7.13.0': - resolution: {integrity: sha512-QWuwm9wcGMAuTsxP+qz6LBBd3Uq8I5Nv8xb0mk54jmNoCyDspnMvVsOxI6IsMmway5d1S9Su2+sCKv1st2l6eA==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/types@7.13.1': - resolution: {integrity: sha512-7K7HMcSQIAND6RBL4kDl24sG/xKM13cA85dc7JnmQXw2cBDngg7c19B++JzvJHRG3zG36n9j1i451GBzRuHchw==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/typescript-estree@7.13.0': - resolution: {integrity: sha512-cAvBvUoobaoIcoqox1YatXOnSl3gx92rCZoMRPzMNisDiM12siGilSM4+dJAekuuHTibI2hVC2fYK79iSFvWjw==} + '@typescript-eslint/typescript-estree@7.18.0': + resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: typescript: '*' @@ -506,33 +467,14 @@ packages: typescript: optional: true - '@typescript-eslint/typescript-estree@7.13.1': - resolution: {integrity: sha512-uxNr51CMV7npU1BxZzYjoVz9iyjckBduFBP0S5sLlh1tXYzHzgZ3BR9SVsNed+LmwKrmnqN3Kdl5t7eZ5TS1Yw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/utils@7.13.0': - resolution: {integrity: sha512-jceD8RgdKORVnB4Y6BqasfIkFhl4pajB1wVxrF4akxD2QPM8GNYjgGwEzYS+437ewlqqrg7Dw+6dhdpjMpeBFQ==} + '@typescript-eslint/utils@7.18.0': + resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 - '@typescript-eslint/utils@7.13.1': - resolution: {integrity: sha512-h5MzFBD5a/Gh/fvNdp9pTfqJAbuQC4sCN2WzuXme71lqFJsZtLbjxfSk4r3p02WIArOF9N94pdsLiGutpDbrXQ==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - - '@typescript-eslint/visitor-keys@7.13.0': - resolution: {integrity: sha512-nxn+dozQx+MK61nn/JP+M4eCkHDSxSLDpgE3WcQo0+fkjEolnaB5jswvIKC4K56By8MMgIho7f1PVxERHEo8rw==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/visitor-keys@7.13.1': - resolution: {integrity: sha512-k/Bfne7lrP7hcb7m9zSsgcBmo+8eicqqfNAJ7uUY+jkTFpKeH2FSkWpFRtimBxgkyvqfu9jTPRbYOvud6isdXA==} + '@typescript-eslint/visitor-keys@7.18.0': + resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} engines: {node: ^18.18.0 || >=20.0.0} acorn-jsx@5.3.2: @@ -724,8 +666,8 @@ packages: supports-color: optional: true - debug@4.3.5: - resolution: {integrity: sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==} + debug@4.3.6: + resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -1319,8 +1261,8 @@ packages: resolution: {integrity: sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==} engines: {node: '>=10'} - minimatch@9.0.4: - resolution: {integrity: sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==} + minimatch@9.0.5: + resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==} engines: {node: '>=16 || 14 >=14.17'} ms@2.1.2: @@ -1634,8 +1576,8 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - typescript-eslint@7.13.0: - resolution: {integrity: sha512-upO0AXxyBwJ4BbiC6CRgAJKtGYha2zw4m1g7TIVPSonwYEuf7vCicw3syjS1OxdDMTz96sZIXl3Jx3vWJLLKFw==} + typescript-eslint@7.18.0: + resolution: {integrity: sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==} engines: {node: ^18.18.0 || >=20.0.0} peerDependencies: eslint: ^8.56.0 @@ -1732,7 +1674,7 @@ snapshots: '@babel/traverse': 7.23.9 '@babel/types': 7.23.9 convert-source-map: 2.0.0 - debug: 4.3.5 + debug: 4.3.6 gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -1898,7 +1840,7 @@ snapshots: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.23.9 '@babel/types': 7.23.9 - debug: 4.3.5 + debug: 4.3.6 globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -1918,7 +1860,7 @@ snapshots: '@eslint-community/regexpp@4.10.0': {} - '@eslint-community/regexpp@4.10.1': {} + '@eslint-community/regexpp@4.11.0': {} '@eslint/config-array@0.16.0': dependencies: @@ -2215,14 +2157,14 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.13.0(@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': dependencies: - '@eslint-community/regexpp': 4.10.1 - '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/type-utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.0 + '@eslint-community/regexpp': 4.11.0 + '@typescript-eslint/parser': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/type-utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.18.0 eslint: 9.5.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -2233,65 +2175,29 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/eslint-plugin@7.13.1(@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: - '@eslint-community/regexpp': 4.10.1 - '@typescript-eslint/parser': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/type-utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 - eslint: 9.5.0 - graphemer: 1.4.0 - ignore: 5.3.1 - natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5)': - dependencies: - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.0 - debug: 4.3.5 + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 eslint: 9.5.0 optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/scope-manager@7.18.0': dependencies: - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.5 - eslint: 9.5.0 - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 - '@typescript-eslint/scope-manager@7.13.0': + '@typescript-eslint/type-utils@7.18.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/visitor-keys': 7.13.0 - - '@typescript-eslint/scope-manager@7.13.1': - dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - - '@typescript-eslint/type-utils@7.13.0(eslint@9.5.0)(typescript@5.4.5)': - dependencies: - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) - debug: 4.3.5 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) + '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + debug: 4.3.6 eslint: 9.5.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: @@ -2299,30 +2205,16 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/type-utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/types@7.18.0': {} + + '@typescript-eslint/typescript-estree@7.18.0(typescript@5.4.5)': dependencies: - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.1(eslint@9.5.0)(typescript@5.4.5) - debug: 4.3.5 - eslint: 9.5.0 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/types@7.13.0': {} - - '@typescript-eslint/types@7.13.1': {} - - '@typescript-eslint/typescript-estree@7.13.0(typescript@5.4.5)': - dependencies: - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/visitor-keys': 7.13.0 - debug: 4.3.5 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/visitor-keys': 7.18.0 + debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 - minimatch: 9.0.4 + minimatch: 9.0.5 semver: 7.6.3 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: @@ -2330,51 +2222,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/typescript-estree@7.13.1(typescript@5.4.5)': - dependencies: - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/visitor-keys': 7.13.1 - debug: 4.3.5 - globby: 11.1.0 - is-glob: 4.0.3 - minimatch: 9.0.4 - semver: 7.6.2 - ts-api-utils: 1.3.0(typescript@5.4.5) - optionalDependencies: - typescript: 5.4.5 - transitivePeerDependencies: - - supports-color - - '@typescript-eslint/utils@7.13.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/utils@7.18.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@typescript-eslint/scope-manager': 7.13.0 - '@typescript-eslint/types': 7.13.0 - '@typescript-eslint/typescript-estree': 7.13.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 7.18.0 + '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) eslint: 9.5.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/utils@7.13.1(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/visitor-keys@7.18.0': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@typescript-eslint/scope-manager': 7.13.1 - '@typescript-eslint/types': 7.13.1 - '@typescript-eslint/typescript-estree': 7.13.1(typescript@5.4.5) - eslint: 9.5.0 - transitivePeerDependencies: - - supports-color - - typescript - - '@typescript-eslint/visitor-keys@7.13.0': - dependencies: - '@typescript-eslint/types': 7.13.0 - eslint-visitor-keys: 3.4.3 - - '@typescript-eslint/visitor-keys@7.13.1': - dependencies: - '@typescript-eslint/types': 7.13.1 + '@typescript-eslint/types': 7.18.0 eslint-visitor-keys: 3.4.3 acorn-jsx@5.3.2(acorn@8.11.3): @@ -2585,7 +2446,7 @@ snapshots: dependencies: ms: 2.1.2 - debug@4.3.5: + debug@4.3.6: dependencies: ms: 2.1.2 @@ -2917,7 +2778,7 @@ snapshots: istanbul-lib-source-maps@4.0.1: dependencies: - debug: 4.3.5 + debug: 4.3.6 istanbul-lib-coverage: 3.2.2 source-map: 0.6.1 transitivePeerDependencies: @@ -3333,7 +3194,7 @@ snapshots: dependencies: brace-expansion: 2.0.1 - minimatch@9.0.4: + minimatch@9.0.5: dependencies: brace-expansion: 2.0.1 @@ -3588,11 +3449,11 @@ snapshots: type-fest@0.21.3: {} - typescript-eslint@7.13.0(eslint@9.5.0)(typescript@5.4.5): + typescript-eslint@7.18.0(eslint@9.5.0)(typescript@5.4.5): dependencies: - '@typescript-eslint/eslint-plugin': 7.13.0(@typescript-eslint/parser@7.13.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.13.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.13.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/parser': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) eslint: 9.5.0 optionalDependencies: typescript: 5.4.5 From 472925551447c7a47a23c8d95cb5088171a84ab9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:24:16 -0400 Subject: [PATCH 47/69] chore(deps): update typescript-eslint monorepo to v8 (#4952) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/package.json | 6 +- api_tests/pnpm-lock.yaml | 158 +++++++++++++++++++-------------------- 2 files changed, 81 insertions(+), 83 deletions(-) diff --git a/api_tests/package.json b/api_tests/package.json index 57b198237..265493159 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -22,8 +22,8 @@ "devDependencies": { "@types/jest": "^29.5.12", "@types/node": "^20.12.4", - "@typescript-eslint/eslint-plugin": "^7.5.0", - "@typescript-eslint/parser": "^7.5.0", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", "download-file-sync": "^1.0.4", "eslint": "^9.0.0", "eslint-plugin-prettier": "^5.1.3", @@ -32,6 +32,6 @@ "prettier": "^3.2.5", "ts-jest": "^29.1.0", "typescript": "^5.4.4", - "typescript-eslint": "^7.13.0" + "typescript-eslint": "^8.0.0" } } diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 65f50a7af..be557650d 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -15,11 +15,11 @@ importers: specifier: ^20.12.4 version: 20.14.13 '@typescript-eslint/eslint-plugin': - specifier: ^7.5.0 - version: 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + specifier: ^8.0.0 + version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) '@typescript-eslint/parser': - specifier: ^7.5.0 - version: 7.18.0(eslint@9.5.0)(typescript@5.4.5) + specifier: ^8.0.0 + version: 8.0.0(eslint@9.5.0)(typescript@5.4.5) download-file-sync: specifier: ^1.0.4 version: 1.0.4 @@ -45,8 +45,8 @@ importers: specifier: ^5.4.4 version: 5.4.5 typescript-eslint: - specifier: ^7.13.0 - version: 7.18.0(eslint@9.5.0)(typescript@5.4.5) + specifier: ^8.0.0 + version: 8.0.0(eslint@9.5.0)(typescript@5.4.5) packages: @@ -419,63 +419,62 @@ packages: '@types/yargs@17.0.32': resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} - '@typescript-eslint/eslint-plugin@7.18.0': - resolution: {integrity: sha512-94EQTWZ40mzBc42ATNIBimBEDltSJ9RQHCC8vc/PDbxi4k8dVwUAv4o98dk50M1zB+JGFxp43FP7f8+FP8R6Sw==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/eslint-plugin@8.0.0': + resolution: {integrity: sha512-STIZdwEQRXAHvNUS6ILDf5z3u95Gc8jzywunxSNqX00OooIemaaNIA0vEgynJlycL5AjabYLLrIyHd4iazyvtg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - '@typescript-eslint/parser': ^7.0.0 - eslint: ^8.56.0 + '@typescript-eslint/parser': ^8.0.0 || ^8.0.0-alpha.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/parser@7.18.0': - resolution: {integrity: sha512-4Z+L8I2OqhZV8qA132M4wNL30ypZGYOQVBfMgxDH/K5UX0PNqTu1c6za9ST5r9+tavvHiTWmBnKzpCJ/GlVFtg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/parser@8.0.0': + resolution: {integrity: sha512-pS1hdZ+vnrpDIxuFXYQpLTILglTjSYJ9MbetZctrUawogUsPdz31DIIRZ9+rab0LhYNTsk88w4fIzVheiTbWOQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 + eslint: ^8.57.0 || ^9.0.0 typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/scope-manager@7.18.0': - resolution: {integrity: sha512-jjhdIE/FPF2B7Z1uzc6i3oWKbGcHb87Qw7AWj6jmEqNOfDFbJWtjt/XfwCpvNkpGWlcJaog5vTR+VV8+w9JflA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/scope-manager@8.0.0': + resolution: {integrity: sha512-V0aa9Csx/ZWWv2IPgTfY7T4agYwJyILESu/PVqFtTFz9RIS823mAze+NbnBI8xiwdX3iqeQbcTYlvB04G9wyQw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/type-utils@7.18.0': - resolution: {integrity: sha512-XL0FJXuCLaDuX2sYqZUUSOJ2sG5/i1AAze+axqmLnSkNEVMVYLF+cbwlB2w8D1tinFuSikHmFta+P+HOofrLeA==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 - typescript: '*' - peerDependenciesMeta: - typescript: - optional: true - - '@typescript-eslint/types@7.18.0': - resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==} - engines: {node: ^18.18.0 || >=20.0.0} - - '@typescript-eslint/typescript-estree@7.18.0': - resolution: {integrity: sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/type-utils@8.0.0': + resolution: {integrity: sha512-mJAFP2mZLTBwAn5WI4PMakpywfWFH5nQZezUQdSKV23Pqo6o9iShQg1hP2+0hJJXP2LnZkWPphdIq4juYYwCeg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' peerDependenciesMeta: typescript: optional: true - '@typescript-eslint/utils@7.18.0': - resolution: {integrity: sha512-kK0/rNa2j74XuHVcoCZxdFBMF+aq/vH83CXAOHieC+2Gis4mF8jJXT5eAfyD3K0sAxtPuwxaIOIOvhwzVDt/kw==} - engines: {node: ^18.18.0 || >=20.0.0} - peerDependencies: - eslint: ^8.56.0 + '@typescript-eslint/types@8.0.0': + resolution: {integrity: sha512-wgdSGs9BTMWQ7ooeHtu5quddKKs5Z5dS+fHLbrQI+ID0XWJLODGMHRfhwImiHoeO2S5Wir2yXuadJN6/l4JRxw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@typescript-eslint/visitor-keys@7.18.0': - resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==} - engines: {node: ^18.18.0 || >=20.0.0} + '@typescript-eslint/typescript-estree@8.0.0': + resolution: {integrity: sha512-5b97WpKMX+Y43YKi4zVcCVLtK5F98dFls3Oxui8LbnmRsseKenbbDinmvxrWegKDMmlkIq/XHuyy0UGLtpCDKg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + + '@typescript-eslint/utils@8.0.0': + resolution: {integrity: sha512-k/oS/A/3QeGLRvOWCg6/9rATJL5rec7/5s1YmdS0ZU6LHveJyGFwBvLhSRBv6i9xaj7etmosp+l+ViN1I9Aj/Q==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + eslint: ^8.57.0 || ^9.0.0 + + '@typescript-eslint/visitor-keys@8.0.0': + resolution: {integrity: sha512-oN0K4nkHuOyF3PVMyETbpP5zp6wfyOvm7tWhTMfoqxSSsPmJIh6JNASuZDlODE8eE+0EB9uar+6+vxr9DBTYOA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} acorn-jsx@5.3.2: resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} @@ -1576,11 +1575,10 @@ packages: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} - typescript-eslint@7.18.0: - resolution: {integrity: sha512-PonBkP603E3tt05lDkbOMyaxJjvKqQrXsnow72sVeOFINDE/qNmnnd+f9b4N+U7W6MXnnYyrhtmF2t08QWwUbA==} - engines: {node: ^18.18.0 || >=20.0.0} + typescript-eslint@8.0.0: + resolution: {integrity: sha512-yQWBJutWL1PmpmDddIOl9/Mi6vZjqNCjqSGBMQ4vsc2Aiodk0SnbQQWPXbSy0HNuKCuGkw1+u4aQ2mO40TdhDQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: - eslint: ^8.56.0 typescript: '*' peerDependenciesMeta: typescript: @@ -2157,14 +2155,14 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 7.18.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/type-utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/type-utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0 eslint: 9.5.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -2175,12 +2173,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/visitor-keys': 8.0.0 debug: 4.3.6 eslint: 9.5.0 optionalDependencies: @@ -2188,29 +2186,29 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/scope-manager@7.18.0': + '@typescript-eslint/scope-manager@8.0.0': dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/visitor-keys': 8.0.0 - '@typescript-eslint/type-utils@7.18.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@8.0.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) - '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) debug: 4.3.6 - eslint: 9.5.0 ts-api-utils: 1.3.0(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: + - eslint - supports-color - '@typescript-eslint/types@7.18.0': {} + '@typescript-eslint/types@8.0.0': {} - '@typescript-eslint/typescript-estree@7.18.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@8.0.0(typescript@5.4.5)': dependencies: - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/visitor-keys': 7.18.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/visitor-keys': 8.0.0 debug: 4.3.6 globby: 11.1.0 is-glob: 4.0.3 @@ -2222,20 +2220,20 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@7.18.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/utils@8.0.0(eslint@9.5.0)(typescript@5.4.5)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@typescript-eslint/scope-manager': 7.18.0 - '@typescript-eslint/types': 7.18.0 - '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.4.5) + '@typescript-eslint/scope-manager': 8.0.0 + '@typescript-eslint/types': 8.0.0 + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) eslint: 9.5.0 transitivePeerDependencies: - supports-color - typescript - '@typescript-eslint/visitor-keys@7.18.0': + '@typescript-eslint/visitor-keys@8.0.0': dependencies: - '@typescript-eslint/types': 7.18.0 + '@typescript-eslint/types': 8.0.0 eslint-visitor-keys: 3.4.3 acorn-jsx@5.3.2(acorn@8.11.3): @@ -3449,15 +3447,15 @@ snapshots: type-fest@0.21.3: {} - typescript-eslint@7.18.0(eslint@9.5.0)(typescript@5.4.5): + typescript-eslint@8.0.0(eslint@9.5.0)(typescript@5.4.5): dependencies: - '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/parser': 7.18.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 7.18.0(eslint@9.5.0)(typescript@5.4.5) - eslint: 9.5.0 + '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) optionalDependencies: typescript: 5.4.5 transitivePeerDependencies: + - eslint - supports-color typescript@5.4.5: {} From c6cbc2f61df8a44062c19c7092be8afc287f0983 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 1 Aug 2024 14:46:59 -0400 Subject: [PATCH 48/69] chore(deps): update dependency typescript to v5.5.4 (#4942) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 72 ++++++++++++++++++++-------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index be557650d..5767132bc 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -16,10 +16,10 @@ importers: version: 20.14.13 '@typescript-eslint/eslint-plugin': specifier: ^8.0.0 - version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) + version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4) '@typescript-eslint/parser': specifier: ^8.0.0 - version: 8.0.0(eslint@9.5.0)(typescript@5.4.5) + version: 8.0.0(eslint@9.5.0)(typescript@5.5.4) download-file-sync: specifier: ^1.0.4 version: 1.0.4 @@ -40,13 +40,13 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5) + version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.5.4) typescript: specifier: ^5.4.4 - version: 5.4.5 + version: 5.5.4 typescript-eslint: specifier: ^8.0.0 - version: 8.0.0(eslint@9.5.0)(typescript@5.4.5) + version: 8.0.0(eslint@9.5.0)(typescript@5.5.4) packages: @@ -1584,8 +1584,8 @@ packages: typescript: optional: true - typescript@5.4.5: - resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==} + typescript@5.5.4: + resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} engines: {node: '>=14.17'} hasBin: true @@ -2155,34 +2155,34 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.5.4) '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/type-utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/type-utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 eslint: 9.5.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 debug: 4.3.6 eslint: 9.5.0 optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color @@ -2191,21 +2191,21 @@ snapshots: '@typescript-eslint/types': 8.0.0 '@typescript-eslint/visitor-keys': 8.0.0 - '@typescript-eslint/type-utils@8.0.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/type-utils@8.0.0(eslint@9.5.0)(typescript@5.5.4)': dependencies: - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) debug: 4.3.6 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - eslint - supports-color '@typescript-eslint/types@8.0.0': {} - '@typescript-eslint/typescript-estree@8.0.0(typescript@5.4.5)': + '@typescript-eslint/typescript-estree@8.0.0(typescript@5.5.4)': dependencies: '@typescript-eslint/types': 8.0.0 '@typescript-eslint/visitor-keys': 8.0.0 @@ -2214,18 +2214,18 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.4.5) + ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.0.0(eslint@9.5.0)(typescript@5.4.5)': + '@typescript-eslint/utils@8.0.0(eslint@9.5.0)(typescript@5.5.4)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 - '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.4.5) + '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) eslint: 9.5.0 transitivePeerDependencies: - supports-color @@ -3414,11 +3414,11 @@ snapshots: dependencies: is-number: 7.0.0 - ts-api-utils@1.3.0(typescript@5.4.5): + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: - typescript: 5.4.5 + typescript: 5.5.4 - ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.4.5): + ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 @@ -3429,7 +3429,7 @@ snapshots: lodash.memoize: 4.1.2 make-error: 1.3.6 semver: 7.6.3 - typescript: 5.4.5 + typescript: 5.5.4 yargs-parser: 21.1.1 optionalDependencies: '@babel/core': 7.23.9 @@ -3447,18 +3447,18 @@ snapshots: type-fest@0.21.3: {} - typescript-eslint@8.0.0(eslint@9.5.0)(typescript@5.4.5): + typescript-eslint@8.0.0(eslint@9.5.0)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.4.5))(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.4.5) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.4.5) + '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) optionalDependencies: - typescript: 5.4.5 + typescript: 5.5.4 transitivePeerDependencies: - eslint - supports-color - typescript@5.4.5: {} + typescript@5.5.4: {} undici-types@5.26.5: {} From f8c7375731180389331fde5b5b5465109310e11d Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 1 Aug 2024 17:04:28 -0400 Subject: [PATCH 49/69] Upgrading deps. (#4955) --- Cargo.lock | 114 ++++++++++++-------- Cargo.toml | 30 +++--- api_tests/package.json | 7 +- api_tests/pnpm-lock.yaml | 204 +++++++++++++++++------------------- api_tests/src/image.spec.ts | 19 ++-- api_tests/src/shared.ts | 3 +- crates/api/Cargo.toml | 4 +- crates/utils/Cargo.toml | 2 +- 8 files changed, 198 insertions(+), 185 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3dfae09d6..8599a31e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -373,7 +373,7 @@ dependencies = [ "getrandom", "once_cell", "version_check", - "zerocopy", + "zerocopy 0.7.35", ] [[package]] @@ -592,9 +592,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.20.0" +version = "0.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2e89b6941c2d1a7045538884d6e760ccfffdf8e1ffc2613d8efa74305e1f3752" +checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" dependencies = [ "bindgen", "cc", @@ -899,9 +899,9 @@ checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c" [[package]] name = "bytemuck" -version = "1.16.1" +version = "1.16.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b236fc92302c97ed75b38da1f4917b5cdda4984745740f153a5d3059e48d725e" +checksum = "102087e286b4677862ea56cf8fc58bb2cdfa8725c40ffb80fe3a008eb7f2fc83" [[package]] name = "byteorder" @@ -911,9 +911,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.6.1" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a12916984aab3fa6e39d655a33e09c0071eb36d6ab3aea5c2d78551f1df6d952" +checksum = "fca2be1d5c43812bae364ee3f30b3afcb7877cf59f4aeb94c66f313a41d2fac9" [[package]] name = "bytestring" @@ -940,9 +940,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.1.6" +version = "1.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aba8f4e9906c7ce3c73463f62a7f0c65183ada1a2d47e397cc8810827f9694f" +checksum = "26a5c3fd7bfa1ce3897a3a3501d362b2d87b7f2583ebcb4a949ec25911025cbc" dependencies = [ "jobserver", "libc", @@ -1143,7 +1143,7 @@ dependencies = [ "ron", "serde", "serde_json", - "toml 0.8.16", + "toml 0.8.19", "yaml-rust", ] @@ -1765,9 +1765,9 @@ dependencies = [ [[package]] name = "email_address" -version = "0.2.7" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46b7a0ac6570e31bfe2c6cf575a576a55af9893d1a6b30b4444e6e90b216bb84" +checksum = "e079f19b08ca6239f47f8ba8509c11cf3ea30095831f7fed61441475edd8c449" [[package]] name = "encoding_rs" @@ -2138,7 +2138,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -2157,7 +2157,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.1.0", - "indexmap 2.2.6", + "indexmap 2.3.0", "slab", "tokio", "tokio-util", @@ -2656,9 +2656,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.2.6" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" +checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" dependencies = [ "equivalent", "hashbrown 0.14.5", @@ -3437,7 +3437,7 @@ dependencies = [ "http-body-util", "hyper 1.4.1", "hyper-util", - "indexmap 2.2.6", + "indexmap 2.3.0", "ipnet", "metrics", "metrics-util", @@ -3952,9 +3952,9 @@ dependencies = [ [[package]] name = "ordered-float" -version = "4.2.1" +version = "4.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ff2cf528c6c03d9ed653d6c4ce1dc0582dc4af309790ad92f07c1cd551b0be" +checksum = "4a91171844676f8c7990ce64959210cd2eaef32c2612c50f9fae9f8aaa6065a6" dependencies = [ "num-traits", ] @@ -4191,7 +4191,7 @@ dependencies = [ "tokio-postgres", "tokio-postgres-generic-rustls", "tokio-util", - "toml 0.8.16", + "toml 0.8.19", "tracing", "tracing-actix-web", "tracing-error", @@ -4269,7 +4269,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42cf17e9a1800f5f396bc67d193dc9411b59012a5876445ef450d449881e1016" dependencies = [ "base64 0.22.1", - "indexmap 2.2.6", + "indexmap 2.3.0", "quick-xml 0.32.0", "serde", "time", @@ -4349,9 +4349,12 @@ checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" [[package]] name = "ppv-lite86" -version = "0.2.17" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" +checksum = "dee4364d9f3b902ef14fab8a1ddffb783a1cb6b4bba3bfc1fa3922732c7de97f" +dependencies = [ + "zerocopy 0.6.6", +] [[package]] name = "pq-sys" @@ -4774,7 +4777,7 @@ dependencies = [ "time", "tokio", "tokio-postgres", - "toml 0.8.16", + "toml 0.8.19", "url", "walkdir", ] @@ -5254,9 +5257,9 @@ dependencies = [ [[package]] name = "scc" -version = "2.1.5" +version = "2.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fadf67e3cf23f8b11a6c8c48a16cb2437381503615acd91094ec7b4686a5a53" +checksum = "05ccfb12511cdb770157ace92d7dda771e498445b78f9886e8cdbc5140a4eced" dependencies = [ "sdd", ] @@ -5298,9 +5301,9 @@ dependencies = [ [[package]] name = "sdd" -version = "1.7.0" +version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85f05a494052771fc5bd0619742363b5e24e5ad72ab3111ec2e27925b8edc5f3" +checksum = "177258b64c0faaa9ffd3c65cd3262c2bc7e2588dbbd9c1641d0346145c1bbda8" [[package]] name = "security-framework" @@ -5377,7 +5380,7 @@ version = "1.0.121" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ab380d7d9f22ef3f21ad3e6c1ebe8e4fc7a2000ccba2e4d71fc96f15b2cb609" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "itoa", "memchr", "ryu", @@ -5424,7 +5427,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_derive", "serde_json", @@ -6168,21 +6171,21 @@ dependencies = [ [[package]] name = "toml" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81967dd0dd2c1ab0bc3468bd7caecc32b8a4aa47d0c8c695d8c2b2108168d62c" +checksum = "a1ed1f98e3fdc28d6d910e6737ae6ab1a93bf1985935a1193e68f93eeb68d24e" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.17", + "toml_edit 0.22.20", ] [[package]] name = "toml_datetime" -version = "0.6.7" +version = "0.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fb9f64314842840f1d940ac544da178732128f1c78c21772e876579e0da1db" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" dependencies = [ "serde", ] @@ -6193,7 +6196,7 @@ version = "0.19.15" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", @@ -6202,15 +6205,15 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.22.17" +version = "0.22.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8d9f8729f5aea9562aac1cc0441f5d6de3cff1ee0c5d67293eeca5eb36ee7c16" +checksum = "583c44c02ad26b0c3f3066fe629275e50627026c51ac2e595cca4c230ce1ce1d" dependencies = [ - "indexmap 2.2.6", + "indexmap 2.3.0", "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.16", + "winnow 0.6.18", ] [[package]] @@ -6752,9 +6755,9 @@ checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" [[package]] name = "version_check" -version = "0.9.4" +version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" [[package]] name = "walkdir" @@ -7142,9 +7145,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.6.16" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b480ae9340fc261e6be3e95a1ba86d54ae3f9171132a73ce8d4bbaf68339507c" +checksum = "68a9bda4691f099d435ad181000724da8e5899daa10713c2d432552b9ccd3a6f" dependencies = [ "memchr", ] @@ -7243,13 +7246,34 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "09041cd90cf85f7f8b2df60c646f853b7f535ce68f85244eb6731cf89fa498ec" +[[package]] +name = "zerocopy" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "854e949ac82d619ee9a14c66a1b674ac730422372ccb759ce0c39cabcf2bf8e6" +dependencies = [ + "byteorder", + "zerocopy-derive 0.6.6", +] + [[package]] name = "zerocopy" version = "0.7.35" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0" dependencies = [ - "zerocopy-derive", + "zerocopy-derive 0.7.35", +] + +[[package]] +name = "zerocopy-derive" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "125139de3f6b9d625c39e2efdd73d41bdac468ccd556556440e322be0e1bbd91" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.72", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index a336bd200..ec04ae46d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -106,9 +106,9 @@ activitypub_federation = { version = "0.5.8", default-features = false, features diesel = "2.1.6" diesel_migrations = "2.1.0" diesel-async = "0.4.1" -serde = { version = "1.0.203", features = ["derive"] } -serde_with = "3.8.1" -actix-web = { version = "4.6.0", default-features = false, features = [ +serde = { version = "1.0.204", features = ["derive"] } +serde_with = "3.9.0" +actix-web = { version = "4.8.0", default-features = false, features = [ "macros", "rustls-0_23", "compress-brotli", @@ -121,7 +121,7 @@ tracing-actix-web = { version = "0.7.11", default-features = false } tracing-error = "0.2.0" tracing-log = "0.2.0" tracing-subscriber = { version = "0.3.18", features = ["env-filter"] } -url = { version = "2.5.0", features = ["serde"] } +url = { version = "2.5.2", features = ["serde"] } reqwest = { version = "0.11.27", default-features = false, features = [ "json", "blocking", @@ -134,19 +134,19 @@ clokwerk = "0.4.0" doku = { version = "0.21.1", features = ["url-2"] } bcrypt = "0.15.1" chrono = { version = "0.4.38", features = ["serde"], default-features = false } -serde_json = { version = "1.0.117", features = ["preserve_order"] } +serde_json = { version = "1.0.121", features = ["preserve_order"] } base64 = "0.22.1" -uuid = { version = "1.8.0", features = ["serde", "v4"] } -async-trait = "0.1.80" +uuid = { version = "1.10.0", features = ["serde", "v4"] } +async-trait = "0.1.81" captcha = "0.0.9" anyhow = { version = "1.0.86", features = [ "backtrace", ] } # backtrace is on by default on nightly, but not stable rust diesel_ltree = "0.3.1" -typed-builder = "0.19.0" +typed-builder = "0.19.1" serial_test = "3.1.1" -tokio = { version = "1.38.0", features = ["full"] } -regex = "1.10.4" +tokio = { version = "1.39.2", features = ["full"] } +regex = "1.10.5" diesel-derive-newtype = "2.1.2" diesel-derive-enum = { version = "2.1.0", features = ["postgres"] } strum = { version = "0.26.3", features = ["derive"] } @@ -161,15 +161,15 @@ ts-rs = { version = "7.1.1", features = [ "chrono-impl", "no-serde-warnings", ] } -rustls = { version = "0.23.9", features = ["ring"] } +rustls = { version = "0.23.12", features = ["ring"] } futures-util = "0.3.30" -tokio-postgres = "0.7.10" +tokio-postgres = "0.7.11" tokio-postgres-rustls = "0.12.0" urlencoding = "2.1.3" enum-map = "2.7" -moka = { version = "0.12.7", features = ["future"] } +moka = { version = "0.12.8", features = ["future"] } i-love-jesus = { version = "0.1.0" } -clap = { version = "4.5.6", features = ["derive", "env"] } +clap = { version = "4.5.13", features = ["derive", "env"] } pretty_assertions = "1.4.0" derive-new = "0.6.0" @@ -201,7 +201,7 @@ tracing-opentelemetry = { workspace = true, optional = true } opentelemetry = { workspace = true, optional = true } console-subscriber = { version = "0.4.0", optional = true } opentelemetry-otlp = { version = "0.12.0", optional = true } -pict-rs = { version = "0.5.15", optional = true } +pict-rs = { version = "0.5.16", optional = true } rustls = { workspace = true } tokio.workspace = true actix-cors = "0.7.0" diff --git a/api_tests/package.json b/api_tests/package.json index 265493159..4fe5a40bd 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -21,17 +21,16 @@ }, "devDependencies": { "@types/jest": "^29.5.12", - "@types/node": "^20.12.4", + "@types/node": "^22.0.2", "@typescript-eslint/eslint-plugin": "^8.0.0", "@typescript-eslint/parser": "^8.0.0", - "download-file-sync": "^1.0.4", - "eslint": "^9.0.0", + "eslint": "^9.8.0", "eslint-plugin-prettier": "^5.1.3", "jest": "^29.5.0", "lemmy-js-client": "0.19.5-alpha.1", "prettier": "^3.2.5", "ts-jest": "^29.1.0", - "typescript": "^5.4.4", + "typescript": "^5.5.4", "typescript-eslint": "^8.0.0" } } diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 5767132bc..3da842f5d 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -12,26 +12,23 @@ importers: specifier: ^29.5.12 version: 29.5.12 '@types/node': - specifier: ^20.12.4 - version: 20.14.13 + specifier: ^22.0.2 + version: 22.0.2 '@typescript-eslint/eslint-plugin': specifier: ^8.0.0 - version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4) + version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4) '@typescript-eslint/parser': specifier: ^8.0.0 - version: 8.0.0(eslint@9.5.0)(typescript@5.5.4) - download-file-sync: - specifier: ^1.0.4 - version: 1.0.4 + version: 8.0.0(eslint@9.8.0)(typescript@5.5.4) eslint: - specifier: ^9.0.0 - version: 9.5.0 + specifier: ^9.8.0 + version: 9.8.0 eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.2.1(eslint@9.5.0)(prettier@3.3.3) + version: 5.2.1(eslint@9.8.0)(prettier@3.3.3) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@20.14.13) + version: 29.7.0(@types/node@22.0.2) lemmy-js-client: specifier: 0.19.5-alpha.1 version: 0.19.5-alpha.1 @@ -40,13 +37,13 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.5.4) + version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4) typescript: - specifier: ^5.4.4 + specifier: ^5.5.4 version: 5.5.4 typescript-eslint: specifier: ^8.0.0 - version: 8.0.0(eslint@9.5.0)(typescript@5.5.4) + version: 8.0.0(eslint@9.8.0)(typescript@5.5.4) packages: @@ -231,24 +228,20 @@ packages: peerDependencies: eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 - '@eslint-community/regexpp@4.10.0': - resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} - engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint-community/regexpp@4.11.0': resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.16.0': - resolution: {integrity: sha512-/jmuSd74i4Czf1XXn7wGRWZCuyaUZ330NH1Bek0Pplatt4Sy1S5haN21SCLLdbeKslQ+S0wEJ+++v5YibSi+Lg==} + '@eslint/config-array@0.17.1': + resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.5.0': - resolution: {integrity: sha512-A7+AOT2ICkodvtsWnxZP4Xxk3NbZ3VMHd8oihydLRGrJgqqdEz1qSeEgXYyT/Cu8h1TWWsQRejIx48mtjZ5y1w==} + '@eslint/js@9.8.0': + resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': @@ -407,8 +400,8 @@ packages: '@types/jest@29.5.12': resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} - '@types/node@20.14.13': - resolution: {integrity: sha512-+bHoGiZb8UiQ0+WEtmph2IWQCjIqg8MDZMAV+ppRRhUZnquF5mQkP/9vpSwJClEiSM/C7fZZExPzfU0vJTyp8w==} + '@types/node@22.0.2': + resolution: {integrity: sha512-yPL6DyFwY5PiMVEwymNeqUTKsDczQBJ/5T7W/46RwLU/VH+AA8aT5TZkvBviLKLbbm0hlfftEkGrNzfRk/fofQ==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -481,8 +474,8 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn@8.11.3: - resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + acorn@8.12.1: + resolution: {integrity: sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==} engines: {node: '>=0.4.0'} hasBin: true @@ -701,9 +694,6 @@ packages: resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} engines: {node: '>=8'} - download-file-sync@1.0.4: - resolution: {integrity: sha512-vH92qNH508jZZA12HQNq/aiMDfagr4JvjFiI17Bi8oYjsxwv5ZVIi7iHkYmUXxOQUr90tcVX+8EPePjAqG1Y0w==} - ejs@3.1.10: resolution: {integrity: sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==} engines: {node: '>=0.10.0'} @@ -752,8 +742,8 @@ packages: eslint-config-prettier: optional: true - eslint-scope@8.0.1: - resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==} + eslint-scope@8.0.2: + resolution: {integrity: sha512-6E4xmrTw5wtxnLA5wYL3WDfhZ/1bUBGOXV0zQvVRDOtrR8D0p6W7fs3JweNYhwRYeGvd/1CKX2se0/2s7Q/nJA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} eslint-visitor-keys@3.4.3: @@ -764,13 +754,13 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.5.0: - resolution: {integrity: sha512-+NAOZFrW/jFTS3dASCGBxX1pkFD0/fsO+hfAkJ4TyYKwgsXZbqzrw+seCYFCcPCYXvnD67tAnglU7GQTz6kcVw==} + eslint@9.8.0: + resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true - espree@10.0.1: - resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==} + espree@10.1.0: + resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} esprima@4.0.1: @@ -1589,8 +1579,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@5.26.5: - resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + undici-types@6.11.1: + resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} update-browserslist-db@1.0.13: resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} @@ -1851,16 +1841,14 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@eslint-community/eslint-utils@4.4.0(eslint@9.5.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.8.0)': dependencies: - eslint: 9.5.0 + eslint: 9.8.0 eslint-visitor-keys: 3.4.3 - '@eslint-community/regexpp@4.10.0': {} - '@eslint-community/regexpp@4.11.0': {} - '@eslint/config-array@0.16.0': + '@eslint/config-array@0.17.1': dependencies: '@eslint/object-schema': 2.1.4 debug: 4.3.4 @@ -1872,7 +1860,7 @@ snapshots: dependencies: ajv: 6.12.6 debug: 4.3.4 - espree: 10.0.1 + espree: 10.1.0 globals: 14.0.0 ignore: 5.3.1 import-fresh: 3.3.0 @@ -1882,7 +1870,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.5.0': {} + '@eslint/js@9.8.0': {} '@eslint/object-schema@2.1.4': {} @@ -1903,7 +1891,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -1916,14 +1904,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@20.14.13) + jest-config: 29.7.0(@types/node@22.0.2) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -1948,7 +1936,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -1966,7 +1954,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 20.14.13 + '@types/node': 22.0.2 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -1988,7 +1976,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.22 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2058,7 +2046,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 20.14.13 + '@types/node': 22.0.2 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -2126,7 +2114,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 20.14.13 + '@types/node': 22.0.2 '@types/istanbul-lib-coverage@2.0.6': {} @@ -2143,9 +2131,9 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/node@20.14.13': + '@types/node@22.0.2': dependencies: - undici-types: 5.26.5 + undici-types: 6.11.1 '@types/stack-utils@2.0.3': {} @@ -2155,15 +2143,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4) '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/type-utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/type-utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 - eslint: 9.5.0 + eslint: 9.8.0 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -2173,14 +2161,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4)': + '@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 debug: 4.3.6 - eslint: 9.5.0 + eslint: 9.8.0 optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -2191,10 +2179,10 @@ snapshots: '@typescript-eslint/types': 8.0.0 '@typescript-eslint/visitor-keys': 8.0.0 - '@typescript-eslint/type-utils@8.0.0(eslint@9.5.0)(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) debug: 4.3.6 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -2220,13 +2208,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.0.0(eslint@9.5.0)(typescript@5.5.4)': + '@typescript-eslint/utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) - eslint: 9.5.0 + eslint: 9.8.0 transitivePeerDependencies: - supports-color - typescript @@ -2236,11 +2224,11 @@ snapshots: '@typescript-eslint/types': 8.0.0 eslint-visitor-keys: 3.4.3 - acorn-jsx@5.3.2(acorn@8.11.3): + acorn-jsx@5.3.2(acorn@8.12.1): dependencies: - acorn: 8.11.3 + acorn: 8.12.1 - acorn@8.11.3: {} + acorn@8.12.1: {} ajv@6.12.6: dependencies: @@ -2419,13 +2407,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@20.14.13): + create-jest@29.7.0(@types/node@22.0.2): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@20.14.13) + jest-config: 29.7.0(@types/node@22.0.2) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -2462,8 +2450,6 @@ snapshots: dependencies: path-type: 4.0.0 - download-file-sync@1.0.4: {} - ejs@3.1.10: dependencies: jake: 10.9.2 @@ -2486,14 +2472,14 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-prettier@5.2.1(eslint@9.5.0)(prettier@3.3.3): + eslint-plugin-prettier@5.2.1(eslint@9.8.0)(prettier@3.3.3): dependencies: - eslint: 9.5.0 + eslint: 9.8.0 prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.9.1 - eslint-scope@8.0.1: + eslint-scope@8.0.2: dependencies: esrecurse: 4.3.0 estraverse: 5.3.0 @@ -2502,13 +2488,13 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint@9.5.0: + eslint@9.8.0: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.5.0) - '@eslint-community/regexpp': 4.10.0 - '@eslint/config-array': 0.16.0 + '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@eslint-community/regexpp': 4.11.0 + '@eslint/config-array': 0.17.1 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.5.0 + '@eslint/js': 9.8.0 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 @@ -2517,9 +2503,9 @@ snapshots: cross-spawn: 7.0.3 debug: 4.3.4 escape-string-regexp: 4.0.0 - eslint-scope: 8.0.1 + eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 - espree: 10.0.1 + espree: 10.1.0 esquery: 1.5.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 @@ -2541,10 +2527,10 @@ snapshots: transitivePeerDependencies: - supports-color - espree@10.0.1: + espree@10.1.0: dependencies: - acorn: 8.11.3 - acorn-jsx: 5.3.2(acorn@8.11.3) + acorn: 8.12.1 + acorn-jsx: 5.3.2(acorn@8.12.1) eslint-visitor-keys: 4.0.0 esprima@4.0.1: {} @@ -2806,7 +2792,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -2826,16 +2812,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@20.14.13): + jest-cli@29.7.0(@types/node@22.0.2): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.14.13) + create-jest: 29.7.0(@types/node@22.0.2) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.14.13) + jest-config: 29.7.0(@types/node@22.0.2) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -2845,7 +2831,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@20.14.13): + jest-config@29.7.0(@types/node@22.0.2): dependencies: '@babel/core': 7.23.9 '@jest/test-sequencer': 29.7.0 @@ -2870,7 +2856,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 20.14.13 + '@types/node': 22.0.2 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -2899,7 +2885,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2909,7 +2895,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 20.14.13 + '@types/node': 22.0.2 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -2948,7 +2934,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -2983,7 +2969,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -3011,7 +2997,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3057,7 +3043,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -3076,7 +3062,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 20.14.13 + '@types/node': 22.0.2 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3085,17 +3071,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 20.14.13 + '@types/node': 22.0.2 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@20.14.13): + jest@29.7.0(@types/node@22.0.2): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@20.14.13) + jest-cli: 29.7.0(@types/node@22.0.2) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3418,12 +3404,12 @@ snapshots: dependencies: typescript: 5.5.4 - ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@20.14.13))(typescript@5.5.4): + ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@20.14.13) + jest: 29.7.0(@types/node@22.0.2) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -3447,11 +3433,11 @@ snapshots: type-fest@0.21.3: {} - typescript-eslint@8.0.0(eslint@9.5.0)(typescript@5.5.4): + typescript-eslint@8.0.0(eslint@9.8.0)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.5.0)(typescript@5.5.4))(eslint@9.5.0)(typescript@5.5.4) - '@typescript-eslint/parser': 8.0.0(eslint@9.5.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.5.0)(typescript@5.5.4) + '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -3460,7 +3446,7 @@ snapshots: typescript@5.5.4: {} - undici-types@5.26.5: {} + undici-types@6.11.1: {} update-browserslist-db@1.0.13(browserslist@4.22.3): dependencies: diff --git a/api_tests/src/image.spec.ts b/api_tests/src/image.spec.ts index fe9470d18..ed96451a2 100644 --- a/api_tests/src/image.spec.ts +++ b/api_tests/src/image.spec.ts @@ -33,7 +33,6 @@ import { sampleImage, sampleSite, } from "./shared"; -const downloadFileSync = require("download-file-sync"); beforeAll(setupLogins); @@ -57,7 +56,8 @@ test("Upload image and delete it", async () => { expect(upload.delete_url).toBeDefined(); // ensure that image download is working. theres probably a better way to do this - const content = downloadFileSync(upload.url); + const response = await fetch(upload.url ?? ""); + const content = await response.text(); expect(content.length).toBeGreaterThan(0); // Ensure that it comes back with the list_media endpoint @@ -92,7 +92,8 @@ test("Upload image and delete it", async () => { expect(delete_).toBe(true); // ensure that image is deleted - const content2 = downloadFileSync(upload.url); + const response2 = await fetch(upload.url ?? ""); + const content2 = await response2.text(); expect(content2).toBe(""); // Ensure that it shows the image is deleted @@ -120,7 +121,8 @@ test("Purge user, uploaded image removed", async () => { expect(upload.delete_url).toBeDefined(); // ensure that image download is working. theres probably a better way to do this - const content = downloadFileSync(upload.url); + const response = await fetch(upload.url ?? ""); + const content = await response.text(); expect(content.length).toBeGreaterThan(0); // purge user @@ -132,7 +134,8 @@ test("Purge user, uploaded image removed", async () => { expect(delete_.success).toBe(true); // ensure that image is deleted - const content2 = downloadFileSync(upload.url); + const response2 = await fetch(upload.url ?? ""); + const content2 = await response2.text(); expect(content2).toBe(""); }); @@ -150,7 +153,8 @@ test("Purge post, linked image removed", async () => { expect(upload.delete_url).toBeDefined(); // ensure that image download is working. theres probably a better way to do this - const content = downloadFileSync(upload.url); + const response = await fetch(upload.url ?? ""); + const content = await response.text(); expect(content.length).toBeGreaterThan(0); let community = await resolveBetaCommunity(user); @@ -170,7 +174,8 @@ test("Purge post, linked image removed", async () => { expect(delete_.success).toBe(true); // ensure that image is deleted - const content2 = downloadFileSync(upload.url); + const response2 = await fetch(upload.url ?? ""); + const content2 = await response2.text(); expect(content2).toBe(""); }); diff --git a/api_tests/src/shared.ts b/api_tests/src/shared.ts index 2ae3d9e21..3ca37dac4 100644 --- a/api_tests/src/shared.ts +++ b/api_tests/src/shared.ts @@ -197,7 +197,7 @@ export async function setupLogins() { // (because last_successful_id is set to current id when federation to an instance is first started) // only needed the first time so do in this try await delay(10_000); - } catch (_) { + } catch { console.log("Communities already exist"); } } @@ -899,7 +899,6 @@ export async function deleteAllImages(api: LemmyHttp) { const imagesRes = await api.listAllMedia({ limit: imageFetchLimit, }); - imagesRes.images; Promise.all( imagesRes.images .map(image => { diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index b98b15d62..9506049ee 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -35,8 +35,8 @@ chrono = { workspace = true } url = { workspace = true } hound = "3.5.1" sitemap-rs = "0.2.1" -totp-rs = { version = "5.5.1", features = ["gen_secret", "otpauth"] } -actix-web-httpauth = "0.8.1" +totp-rs = { version = "5.6.0", features = ["gen_secret", "otpauth"] } +actix-web-httpauth = "0.8.2" [dev-dependencies] serial_test = { workspace = true } diff --git a/crates/utils/Cargo.toml b/crates/utils/Cargo.toml index 9125f34a2..e94fce9d6 100644 --- a/crates/utils/Cargo.toml +++ b/crates/utils/Cargo.toml @@ -79,7 +79,7 @@ lettre = { version = "0.11.7", default-features = false, features = [ "tokio1-rustls-tls", "smtp-transport", ], optional = true } -markdown-it = { version = "0.6.0", optional = true } +markdown-it = { version = "0.6.1", optional = true } ts-rs = { workspace = true, optional = true } enum-map = { workspace = true, optional = true } cfg-if = "1" From 33fd31754af6cc55436ec65061c6a38cbd2b6d68 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Sun, 4 Aug 2024 09:45:53 -0400 Subject: [PATCH 50/69] Adding a URL max length lemmy error. (#4960) * Adding a URL max length error. - Also increasing the post.url max length to 2000 (seems standard) - I ran into this when fixing torrent support, which often use longer urls. * Fixing sql_format. --- crates/api_crud/src/post/create.rs | 6 +-- crates/api_crud/src/post/update.rs | 6 +-- crates/apub/src/objects/post.rs | 4 +- crates/db_schema/src/schema.rs | 2 +- crates/utils/src/error.rs | 1 + crates/utils/src/utils/validation.rs | 38 ++++++++++++++----- .../down.sql | 3 ++ .../up.sql | 5 +++ 8 files changed, 47 insertions(+), 18 deletions(-) create mode 100644 migrations/2024-08-03-155932_increase_post_url_max_length/down.sql create mode 100644 migrations/2024-08-03-155932_increase_post_url_max_length/up.sql diff --git a/crates/api_crud/src/post/create.rs b/crates/api_crud/src/post/create.rs index 0f6abc2aa..a0f0b7525 100644 --- a/crates/api_crud/src/post/create.rs +++ b/crates/api_crud/src/post/create.rs @@ -35,11 +35,11 @@ use lemmy_utils::{ utils::{ slurs::check_slurs, validation::{ - check_url_scheme, is_url_blocked, is_valid_alt_text_field, is_valid_body_field, is_valid_post_title, + is_valid_url, }, }, }; @@ -69,11 +69,11 @@ pub async fn create_post( if let Some(url) = &url { is_url_blocked(url, &url_blocklist)?; - check_url_scheme(url)?; + is_valid_url(url)?; } if let Some(custom_thumbnail) = &custom_thumbnail { - check_url_scheme(custom_thumbnail)?; + is_valid_url(custom_thumbnail)?; } if let Some(alt_text) = &data.alt_text { diff --git a/crates/api_crud/src/post/update.rs b/crates/api_crud/src/post/update.rs index cd4b2d41b..835398596 100644 --- a/crates/api_crud/src/post/update.rs +++ b/crates/api_crud/src/post/update.rs @@ -28,11 +28,11 @@ use lemmy_utils::{ utils::{ slurs::check_slurs, validation::{ - check_url_scheme, is_url_blocked, is_valid_alt_text_field, is_valid_body_field, is_valid_post_title, + is_valid_url, }, }, }; @@ -77,11 +77,11 @@ pub async fn update_post( if let Some(Some(url)) = &url { is_url_blocked(url, &url_blocklist)?; - check_url_scheme(url)?; + is_valid_url(url)?; } if let Some(Some(custom_thumbnail)) = &custom_thumbnail { - check_url_scheme(custom_thumbnail)?; + is_valid_url(custom_thumbnail)?; } let post_id = data.post_id; diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 7e4254840..0364039bb 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -41,7 +41,7 @@ use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::{ error::{LemmyError, LemmyErrorType, LemmyResult}, spawn_try_task, - utils::{markdown::markdown_to_html, slurs::check_slurs_opt, validation::check_url_scheme}, + utils::{markdown::markdown_to_html, slurs::check_slurs_opt, validation::is_valid_url}, }; use std::ops::Deref; use stringreader::StringReader; @@ -221,7 +221,7 @@ impl Object for ApubPost { }; if let Some(url) = &url { - check_url_scheme(url)?; + is_valid_url(url)?; } let alt_text = first_attachment.cloned().and_then(Attachment::alt_text); diff --git a/crates/db_schema/src/schema.rs b/crates/db_schema/src/schema.rs index c3102b578..fc418ec28 100644 --- a/crates/db_schema/src/schema.rs +++ b/crates/db_schema/src/schema.rs @@ -711,7 +711,7 @@ diesel::table! { id -> Int4, #[max_length = 200] name -> Varchar, - #[max_length = 512] + #[max_length = 2000] url -> Nullable, body -> Nullable, creator_id -> Int4, diff --git a/crates/utils/src/error.rs b/crates/utils/src/error.rs index 542888612..860dad6fd 100644 --- a/crates/utils/src/error.rs +++ b/crates/utils/src/error.rs @@ -180,6 +180,7 @@ pub enum LemmyErrorType { InboxTimeout, Unknown(String), CantDeleteSite, + UrlLengthOverflow, } cfg_if! { diff --git a/crates/utils/src/utils/validation.rs b/crates/utils/src/utils/validation.rs index 2f9e27f5c..0a59e2fea 100644 --- a/crates/utils/src/utils/validation.rs +++ b/crates/utils/src/utils/validation.rs @@ -21,6 +21,7 @@ const ALLOWED_POST_URL_SCHEMES: [&str; 3] = ["http", "https", "magnet"]; const BODY_MAX_LENGTH: usize = 10000; const POST_BODY_MAX_LENGTH: usize = 50000; const BIO_MAX_LENGTH: usize = 300; +const URL_MAX_LENGTH: usize = 2000; const ALT_TEXT_MAX_LENGTH: usize = 1500; const SITE_NAME_MAX_LENGTH: usize = 20; const SITE_NAME_MIN_LENGTH: usize = 1; @@ -284,11 +285,17 @@ pub fn check_site_visibility_valid( } } -pub fn check_url_scheme(url: &Url) -> LemmyResult<()> { +pub fn is_valid_url(url: &Url) -> LemmyResult<()> { if !ALLOWED_POST_URL_SCHEMES.contains(&url.scheme()) { Err(LemmyErrorType::InvalidUrlScheme)? } + max_length_check( + url.as_str(), + URL_MAX_LENGTH, + LemmyErrorType::UrlLengthOverflow, + )?; + Ok(()) } @@ -349,7 +356,6 @@ mod tests { utils::validation::{ build_and_check_regex, check_site_visibility_valid, - check_url_scheme, check_urls_are_valid, clean_url_params, is_url_blocked, @@ -358,11 +364,13 @@ mod tests { is_valid_display_name, is_valid_matrix_id, is_valid_post_title, + is_valid_url, site_description_length_check, site_name_length_check, BIO_MAX_LENGTH, SITE_DESCRIPTION_MAX_LENGTH, SITE_NAME_MAX_LENGTH, + URL_MAX_LENGTH, }, }; use pretty_assertions::assert_eq; @@ -580,15 +588,27 @@ mod tests { } #[test] - fn test_check_url_scheme() -> LemmyResult<()> { - assert!(check_url_scheme(&Url::parse("http://example.com")?).is_ok()); - assert!(check_url_scheme(&Url::parse("https://example.com")?).is_ok()); - assert!(check_url_scheme(&Url::parse("https://example.com")?).is_ok()); - assert!(check_url_scheme(&Url::parse("ftp://example.com")?).is_err()); - assert!(check_url_scheme(&Url::parse("javascript:void")?).is_err()); + fn test_check_url_valid() -> LemmyResult<()> { + assert!(is_valid_url(&Url::parse("http://example.com")?).is_ok()); + assert!(is_valid_url(&Url::parse("https://example.com")?).is_ok()); + assert!(is_valid_url(&Url::parse("https://example.com")?).is_ok()); + assert!(is_valid_url(&Url::parse("ftp://example.com")?) + .is_err_and(|e| e.error_type.eq(&LemmyErrorType::InvalidUrlScheme))); + assert!(is_valid_url(&Url::parse("javascript:void")?) + .is_err_and(|e| e.error_type.eq(&LemmyErrorType::InvalidUrlScheme))); let magnet_link="magnet:?xt=urn:btih:4b390af3891e323778959d5abfff4b726510f14c&dn=Ravel%20Complete%20Piano%20Sheet%20Music%20-%20Public%20Domain&tr=udp%3A%2F%2Fopen.tracker.cl%3A1337%2Fannounce"; - assert!(check_url_scheme(&Url::parse(magnet_link)?).is_ok()); + assert!(is_valid_url(&Url::parse(magnet_link)?).is_ok()); + + // Also make sure the length overflow hits an error + let mut long_str = "http://example.com/test=".to_string(); + for _ in 1..URL_MAX_LENGTH { + long_str.push('X'); + } + let long_url = Url::parse(&long_str)?; + assert!( + is_valid_url(&long_url).is_err_and(|e| e.error_type.eq(&LemmyErrorType::UrlLengthOverflow)) + ); Ok(()) } diff --git a/migrations/2024-08-03-155932_increase_post_url_max_length/down.sql b/migrations/2024-08-03-155932_increase_post_url_max_length/down.sql new file mode 100644 index 000000000..d25918578 --- /dev/null +++ b/migrations/2024-08-03-155932_increase_post_url_max_length/down.sql @@ -0,0 +1,3 @@ +ALTER TABLE post + ALTER COLUMN url TYPE varchar(512); + diff --git a/migrations/2024-08-03-155932_increase_post_url_max_length/up.sql b/migrations/2024-08-03-155932_increase_post_url_max_length/up.sql new file mode 100644 index 000000000..7c6818d22 --- /dev/null +++ b/migrations/2024-08-03-155932_increase_post_url_max_length/up.sql @@ -0,0 +1,5 @@ +-- Change the post url max limit to 2000 +-- From here: https://stackoverflow.com/questions/417142/what-is-the-maximum-length-of-a-url-in-different-browsers#417184 +ALTER TABLE post + ALTER COLUMN url TYPE varchar(2000); + From eff87b2764df6e6b0d18e9df8a449be6cb374e1e Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 5 Aug 2024 22:25:18 -0400 Subject: [PATCH 51/69] Upgrading arm image. (#4962) --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index c7d5c9aa5..156d30dcc 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -5,7 +5,7 @@ ARG RUST_RELEASE_MODE=debug ARG AMD_BUILDER_IMAGE=rust:${RUST_VERSION} # Repo: https://github.com/raskyld/lemmy-cross-toolchains -ARG ARM_BUILDER_IMAGE="ghcr.io/raskyld/aarch64-lemmy-linux-gnu:v0.3.0" +ARG ARM_BUILDER_IMAGE="ghcr.io/raskyld/aarch64-lemmy-linux-gnu:v0.4.0" ARG AMD_RUNNER_IMAGE=debian:bookworm-slim ARG ARM_RUNNER_IMAGE=debian:bookworm-slim From 88fbcea2463550d1a61927edb1ab151348dcb92a Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 6 Aug 2024 10:32:41 -0400 Subject: [PATCH 52/69] Version 0.19.6-beta.3 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8599a31e1..5c8f7738d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,7 +2804,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-web", @@ -2833,7 +2833,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-web", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "accept-language", "activitypub_federation", @@ -2892,7 +2892,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-web", @@ -2929,7 +2929,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "anyhow", "clap", @@ -2944,7 +2944,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "anyhow", @@ -2983,7 +2983,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "actix-web", "chrono", @@ -3005,7 +3005,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "chrono", "diesel", @@ -3025,7 +3025,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "diesel", "diesel-async", @@ -3037,7 +3037,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-web", @@ -3068,7 +3068,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-web", @@ -3092,7 +3092,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "activitypub_federation", "actix-cors", @@ -3136,7 +3136,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index ec04ae46d..c021d9d43 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.6-beta.2" +version = "0.19.6-beta.3" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.6-beta.2", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.6-beta.2", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.6-beta.2", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.6-beta.2", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.6-beta.2", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.6-beta.2", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.6-beta.2", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.6-beta.2", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.6-beta.2", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.6-beta.2", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.6-beta.2", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.3", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.3", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.3", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.3", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.3", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.3", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.3", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.3", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.3", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.3", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.3", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index 088a27703..179f68843 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit 088a27703ffa65e069dfbf341ee9bd44ec4c45c5 +Subproject commit 179f6884398d3536d16382df5dc40da4e47835aa From 606545ccaf7b7158d9aa1d2b805564a5a1c97886 Mon Sep 17 00:00:00 2001 From: phiresky Date: Wed, 7 Aug 2024 16:35:08 +0200 Subject: [PATCH 53/69] fix: Run extract_opengraph_data only on first 64kB of data and if Content-Type html (#4957) * fix: Run extract_opengraph_data only on first 64kB of data and if data is not binary. * use mime type for determination * chore: simplify collect function --- crates/api_common/src/request.rs | 70 ++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 8 deletions(-) diff --git a/crates/api_common/src/request.rs b/crates/api_common/src/request.rs index ddbb3dd0c..de6ba4f39 100644 --- a/crates/api_common/src/request.rs +++ b/crates/api_common/src/request.rs @@ -8,6 +8,7 @@ use crate::{ use activitypub_federation::config::Data; use chrono::{DateTime, Utc}; use encoding_rs::{Encoding, UTF_8}; +use futures::StreamExt; use lemmy_db_schema::{ newtypes::DbUrl, source::{ @@ -23,7 +24,12 @@ use lemmy_utils::{ VERSION, }; use mime::Mime; -use reqwest::{header::CONTENT_TYPE, Client, ClientBuilder}; +use reqwest::{ + header::{CONTENT_TYPE, RANGE}, + Client, + ClientBuilder, + Response, +}; use reqwest_middleware::ClientWithMiddleware; use serde::{Deserialize, Serialize}; use tracing::info; @@ -44,7 +50,17 @@ pub fn client_builder(settings: &Settings) -> ClientBuilder { #[tracing::instrument(skip_all)] pub async fn fetch_link_metadata(url: &Url, context: &LemmyContext) -> LemmyResult { info!("Fetching site metadata for url: {}", url); - let response = context.client().get(url.as_str()).send().await?; + // We only fetch the first 64kB of data in order to not waste bandwidth especially for large + // binary files + let bytes_to_fetch = 64 * 1024; + let response = context + .client() + .get(url.as_str()) + // we only need the first chunk of data. Note that we do not check for Accept-Range so the + // server may ignore this and still respond with the full response + .header(RANGE, format!("bytes=0-{}", bytes_to_fetch - 1)) /* -1 because inclusive */ + .send() + .await?; let content_type: Option = response .headers() @@ -52,19 +68,57 @@ pub async fn fetch_link_metadata(url: &Url, context: &LemmyContext) -> LemmyResu .and_then(|h| h.to_str().ok()) .and_then(|h| h.parse().ok()); - // Can't use .text() here, because it only checks the content header, not the actual bytes - // https://github.com/LemmyNet/lemmy/issues/1964 - let html_bytes = response.bytes().await.map_err(LemmyError::from)?.to_vec(); + let opengraph_data = { + // if the content type is not text/html, we don't need to parse it + let is_html = content_type + .as_ref() + .map(|c| { + (c.type_() == mime::TEXT && c.subtype() == mime::HTML) + || + // application/xhtml+xml is a subset of HTML + (c.type_() == mime::APPLICATION && c.subtype() == "xhtml") + }) + .unwrap_or(false); + if !is_html { + Default::default() + } else { + // Can't use .text() here, because it only checks the content header, not the actual bytes + // https://github.com/LemmyNet/lemmy/issues/1964 + // So we want to do deep inspection of the actually returned bytes but need to be careful not + // spend too much time parsing binary data as HTML - let opengraph_data = extract_opengraph_data(&html_bytes, url) - .map_err(|e| info!("{e}")) - .unwrap_or_default(); + // only take first bytes regardless of how many bytes the server returns + let html_bytes = collect_bytes_until_limit(response, bytes_to_fetch).await?; + extract_opengraph_data(&html_bytes, url) + .map_err(|e| info!("{e}")) + .unwrap_or_default() + } + }; Ok(LinkMetadata { opengraph_data, content_type: content_type.map(|c| c.to_string()), }) } +async fn collect_bytes_until_limit( + response: Response, + requested_bytes: usize, +) -> Result, LemmyError> { + let mut stream = response.bytes_stream(); + let mut bytes = Vec::with_capacity(requested_bytes); + while let Some(chunk) = stream.next().await { + let chunk = chunk.map_err(LemmyError::from)?; + // we may go over the requested size here but the important part is we don't keep aggregating + // more chunks than needed + bytes.extend_from_slice(&chunk); + if bytes.len() >= requested_bytes { + bytes.truncate(requested_bytes); + break; + } + } + Ok(bytes) +} + /// Generates and saves a post thumbnail and metadata. /// /// Takes a callback to generate a send activity task, so that post can be federated with metadata. From 128e78f7c22279fec27d3213a05b440cb1f8db59 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 8 Aug 2024 20:01:58 -0400 Subject: [PATCH 54/69] Version 0.19.6-beta.4 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5c8f7738d..d2d40d5eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,7 +2804,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-web", @@ -2833,7 +2833,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-web", @@ -2870,7 +2870,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "accept-language", "activitypub_federation", @@ -2892,7 +2892,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-web", @@ -2929,7 +2929,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "anyhow", "clap", @@ -2944,7 +2944,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "anyhow", @@ -2983,7 +2983,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "actix-web", "chrono", @@ -3005,7 +3005,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "chrono", "diesel", @@ -3025,7 +3025,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "diesel", "diesel-async", @@ -3037,7 +3037,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-web", @@ -3068,7 +3068,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-web", @@ -3092,7 +3092,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "activitypub_federation", "actix-cors", @@ -3136,7 +3136,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index c021d9d43..228ff69f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.6-beta.3" +version = "0.19.6-beta.4" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.6-beta.3", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.6-beta.3", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.6-beta.3", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.6-beta.3", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.6-beta.3", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.6-beta.3", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.6-beta.3", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.6-beta.3", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.6-beta.3", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.6-beta.3", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.6-beta.3", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.4", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.4", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.4", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.4", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.4", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.4", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.4", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.4", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.4", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.4", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.4", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } From ea18d462b0d5653935558bef4226bf748fc99b3b Mon Sep 17 00:00:00 2001 From: flamingos-cant <45780476+flamingo-cant-draw@users.noreply.github.com> Date: Tue, 13 Aug 2024 19:56:26 +0100 Subject: [PATCH 55/69] Throw error when non-mod posts to mod-only comm (#4966) --- crates/apub/src/objects/post.rs | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/crates/apub/src/objects/post.rs b/crates/apub/src/objects/post.rs index 0364039bb..44e842413 100644 --- a/crates/apub/src/objects/post.rs +++ b/crates/apub/src/objects/post.rs @@ -41,7 +41,11 @@ use lemmy_db_views_actor::structs::CommunityModeratorView; use lemmy_utils::{ error::{LemmyError, LemmyErrorType, LemmyResult}, spawn_try_task, - utils::{markdown::markdown_to_html, slurs::check_slurs_opt, validation::is_valid_url}, + utils::{ + markdown::markdown_to_html, + slurs::check_slurs_opt, + validation::{is_url_blocked, is_valid_url}, + }, }; use std::ops::Deref; use stringreader::StringReader; @@ -180,8 +184,15 @@ impl Object for ApubPost { let creator = page.creator()?.dereference(context).await?; let community = page.community(context).await?; if community.posting_restricted_to_mods { - CommunityModeratorView::is_community_moderator(&mut context.pool(), community.id, creator.id) - .await?; + let is_mod = CommunityModeratorView::is_community_moderator( + &mut context.pool(), + community.id, + creator.id, + ) + .await?; + if !is_mod { + Err(LemmyErrorType::OnlyModsCanPostInCommunity)? + } } let mut name = page .name @@ -220,14 +231,16 @@ impl Object for ApubPost { None }; + let url_blocklist = get_url_blocklist(context).await?; + if let Some(url) = &url { + is_url_blocked(url, &url_blocklist)?; is_valid_url(url)?; } let alt_text = first_attachment.cloned().and_then(Attachment::alt_text); let slur_regex = &local_site_opt_to_slur_regex(&local_site); - let url_blocklist = get_url_blocklist(context).await?; let body = read_from_string_or_source_opt(&page.content, &page.media_type, &page.source); let body = process_markdown_opt(&body, slur_regex, &url_blocklist, context).await?; From 63a686d390e441216718a3d64408336409890791 Mon Sep 17 00:00:00 2001 From: Richard Schwab Date: Tue, 13 Aug 2024 22:18:26 +0200 Subject: [PATCH 56/69] Approve applications in transaction (#4970) * Implement tests for registration application count and list api * Use transaction when approving applications to ensure consistent approval state --- Cargo.lock | 1 + crates/api/Cargo.toml | 1 + .../site/registration_applications/approve.rs | 56 ++- .../site/registration_applications/list.rs | 3 +- .../src/site/registration_applications/mod.rs | 2 + .../site/registration_applications/tests.rs | 428 ++++++++++++++++++ .../registration_applications/unread_count.rs | 3 +- crates/api_crud/src/site/create.rs | 4 +- 8 files changed, 474 insertions(+), 24 deletions(-) create mode 100644 crates/api/src/site/registration_applications/tests.rs diff --git a/Cargo.lock b/Cargo.lock index d2d40d5eb..a53843f6e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2817,6 +2817,7 @@ dependencies = [ "elementtree", "hound", "lemmy_api_common", + "lemmy_api_crud", "lemmy_db_schema", "lemmy_db_views", "lemmy_db_views_actor", diff --git a/crates/api/Cargo.toml b/crates/api/Cargo.toml index 9506049ee..87879f6cd 100644 --- a/crates/api/Cargo.toml +++ b/crates/api/Cargo.toml @@ -43,3 +43,4 @@ serial_test = { workspace = true } tokio = { workspace = true } elementtree = "1.2.3" pretty_assertions = { workspace = true } +lemmy_api_crud = { workspace = true } diff --git a/crates/api/src/site/registration_applications/approve.rs b/crates/api/src/site/registration_applications/approve.rs index 823af54c4..dcde78117 100644 --- a/crates/api/src/site/registration_applications/approve.rs +++ b/crates/api/src/site/registration_applications/approve.rs @@ -1,4 +1,5 @@ -use actix_web::web::{Data, Json}; +use activitypub_federation::config::Data; +use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, site::{ApproveRegistrationApplication, RegistrationApplicationResponse}, @@ -10,10 +11,13 @@ use lemmy_db_schema::{ registration_application::{RegistrationApplication, RegistrationApplicationUpdateForm}, }, traits::Crud, - utils::diesel_string_update, + utils::{diesel_string_update, get_conn}, }; use lemmy_db_views::structs::{LocalUserView, RegistrationApplicationView}; -use lemmy_utils::{error::LemmyResult, LemmyErrorType}; +use lemmy_utils::{ + error::{LemmyError, LemmyResult}, + LemmyErrorType, +}; pub async fn approve_registration_application( data: Json, @@ -25,34 +29,46 @@ pub async fn approve_registration_application( // Only let admins do this is_admin(&local_user_view)?; - // Update the registration with reason, admin_id - let deny_reason = diesel_string_update(data.deny_reason.as_deref()); - let app_form = RegistrationApplicationUpdateForm { - admin_id: Some(Some(local_user_view.person.id)), - deny_reason, - }; + let pool = &mut context.pool(); + let conn = &mut get_conn(pool).await?; + let tx_data = data.clone(); + let approved_user_id = conn + .build_transaction() + .run(|conn| { + Box::pin(async move { + // Update the registration with reason, admin_id + let deny_reason = diesel_string_update(tx_data.deny_reason.as_deref()); + let app_form = RegistrationApplicationUpdateForm { + admin_id: Some(Some(local_user_view.person.id)), + deny_reason, + }; - let registration_application = - RegistrationApplication::update(&mut context.pool(), app_id, &app_form).await?; + let registration_application = + RegistrationApplication::update(&mut conn.into(), app_id, &app_form).await?; - // Update the local_user row - let local_user_form = LocalUserUpdateForm { - accepted_application: Some(data.approve), - ..Default::default() - }; + // Update the local_user row + let local_user_form = LocalUserUpdateForm { + accepted_application: Some(tx_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?; + let approved_user_id = registration_application.local_user_id; + LocalUser::update(&mut conn.into(), approved_user_id, &local_user_form).await?; + + Ok::<_, LemmyError>(approved_user_id) + }) as _ + }) + .await?; if data.approve { let approved_local_user_view = LocalUserView::read(&mut context.pool(), approved_user_id) .await? .ok_or(LemmyErrorType::CouldntFindLocalUser)?; - if approved_local_user_view.local_user.email.is_some() { + // Email sending may fail, but this won't revert the application approval send_application_approved_email(&approved_local_user_view, context.settings()).await?; } - } + }; // Read the view let registration_application = RegistrationApplicationView::read(&mut context.pool(), app_id) diff --git a/crates/api/src/site/registration_applications/list.rs b/crates/api/src/site/registration_applications/list.rs index df86b11d5..877e83796 100644 --- a/crates/api/src/site/registration_applications/list.rs +++ b/crates/api/src/site/registration_applications/list.rs @@ -1,4 +1,5 @@ -use actix_web::web::{Data, Json, Query}; +use activitypub_federation::config::Data; +use actix_web::web::{Json, Query}; use lemmy_api_common::{ context::LemmyContext, site::{ListRegistrationApplications, ListRegistrationApplicationsResponse}, diff --git a/crates/api/src/site/registration_applications/mod.rs b/crates/api/src/site/registration_applications/mod.rs index e904f597d..c9a63cdef 100644 --- a/crates/api/src/site/registration_applications/mod.rs +++ b/crates/api/src/site/registration_applications/mod.rs @@ -1,4 +1,6 @@ pub mod approve; pub mod get; pub mod list; +#[cfg(test)] +mod tests; pub mod unread_count; diff --git a/crates/api/src/site/registration_applications/tests.rs b/crates/api/src/site/registration_applications/tests.rs new file mode 100644 index 000000000..062fa550f --- /dev/null +++ b/crates/api/src/site/registration_applications/tests.rs @@ -0,0 +1,428 @@ +use crate::site::registration_applications::{ + approve::approve_registration_application, + list::list_registration_applications, + unread_count::get_unread_registration_application_count, +}; +use activitypub_federation::config::Data; +use actix_web::web::{Json, Query}; +use lemmy_api_common::{ + context::LemmyContext, + site::{ + ApproveRegistrationApplication, + EditSite, + GetUnreadRegistrationApplicationCountResponse, + ListRegistrationApplicationsResponse, + }, +}; +use lemmy_api_crud::site::update::update_site; +use lemmy_db_schema::{ + newtypes::InstanceId, + source::{ + instance::Instance, + local_site::{LocalSite, LocalSiteInsertForm}, + local_site_rate_limit::{LocalSiteRateLimit, LocalSiteRateLimitInsertForm}, + local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm}, + person::{Person, PersonInsertForm}, + registration_application::{RegistrationApplication, RegistrationApplicationInsertForm}, + site::{Site, SiteInsertForm}, + }, + traits::Crud, + utils::DbPool, + RegistrationMode, +}; +use lemmy_db_views::structs::LocalUserView; +use lemmy_utils::{error::LemmyResult, LemmyErrorType, CACHE_DURATION_API}; +use serial_test::serial; + +#[allow(clippy::unwrap_used)] +async fn create_test_site(context: &Data) -> LemmyResult<(Instance, LocalUserView)> { + let pool = &mut context.pool(); + + let inserted_instance = Instance::read_or_create(pool, "my_domain.tld".to_string()) + .await + .expect("Create test instance"); + + let admin_person = Person::create( + pool, + &PersonInsertForm::test_form(inserted_instance.id, "admin"), + ) + .await?; + LocalUser::create( + pool, + &LocalUserInsertForm::test_form_admin(admin_person.id), + vec![], + ) + .await?; + + let admin_local_user_view = LocalUserView::read_person(pool, admin_person.id) + .await? + .unwrap(); + + let site_form = SiteInsertForm::builder() + .name("test site".to_string()) + .instance_id(inserted_instance.id) + .build(); + let site = Site::create(pool, &site_form).await.unwrap(); + + // Create a local site, since this is necessary for determining if email verification is + // required + let local_site_form = LocalSiteInsertForm::builder() + .site_id(site.id) + .require_email_verification(Some(true)) + .application_question(Some(".".to_string())) + .registration_mode(Some(RegistrationMode::RequireApplication)) + .site_setup(Some(true)) + .build(); + let local_site = LocalSite::create(pool, &local_site_form).await.unwrap(); + + // Required to have a working local SiteView when updating the site to change email verification + // requirement or registration mode + let rate_limit_form = LocalSiteRateLimitInsertForm::builder() + .local_site_id(local_site.id) + .build(); + LocalSiteRateLimit::create(pool, &rate_limit_form) + .await + .unwrap(); + + Ok((inserted_instance, admin_local_user_view)) +} + +async fn signup( + pool: &mut DbPool<'_>, + instance_id: InstanceId, + name: &str, + email: Option<&str>, +) -> LemmyResult<(LocalUser, RegistrationApplication)> { + let person_insert_form = PersonInsertForm::test_form(instance_id, name); + let person = Person::create(pool, &person_insert_form).await?; + + let local_user_insert_form = match email { + Some(email) => LocalUserInsertForm { + email: Some(email.to_string()), + email_verified: Some(false), + ..LocalUserInsertForm::test_form(person.id) + }, + None => LocalUserInsertForm::test_form(person.id), + }; + + let local_user = LocalUser::create(pool, &local_user_insert_form, vec![]).await?; + + let application_insert_form = RegistrationApplicationInsertForm { + local_user_id: local_user.id, + answer: "x".to_string(), + }; + let application = RegistrationApplication::create(pool, &application_insert_form).await?; + + Ok((local_user, application)) +} + +#[allow(clippy::unwrap_used)] +async fn get_application_statuses( + context: &Data, + admin: LocalUserView, +) -> LemmyResult<( + Json, + Json, + Json, +)> { + let application_count = + get_unread_registration_application_count(context.reset_request_count(), admin.clone()).await?; + + let unread_applications = list_registration_applications( + Query::from_query("unread_only=true").unwrap(), + context.reset_request_count(), + admin.clone(), + ) + .await?; + + let all_applications = list_registration_applications( + Query::from_query("unread_only=false").unwrap(), + context.reset_request_count(), + admin, + ) + .await?; + + Ok((application_count, unread_applications, all_applications)) +} + +#[allow(clippy::indexing_slicing)] +#[allow(clippy::unwrap_used)] +#[tokio::test] +#[serial] +async fn test_application_approval() -> LemmyResult<()> { + let context = LemmyContext::init_test_context().await; + let pool = &mut context.pool(); + + let (instance, admin_local_user_view) = create_test_site(&context).await?; + + // Non-unread counts unfortunately are duplicated due to different types (i64 vs usize) + let mut expected_total_applications = 0; + let mut expected_unread_applications = 0u8; + + let (local_user_with_email, app_with_email) = + signup(pool, instance.id, "user_w_email", Some("lemmy@localhost")).await?; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // When email verification is required and the email is not verified the application should not + // be visible to admins + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + LocalUser::update( + pool, + local_user_with_email.id, + &LocalUserUpdateForm { + email_verified: Some(true), + ..Default::default() + }, + ) + .await?; + + expected_total_applications += 1; + expected_unread_applications += 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // When email verification is required and the email is verified the application should be + // visible to admins + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert!( + !unread_applications.registration_applications[0] + .creator_local_user + .accepted_application + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + let approval = approve_registration_application( + Json(ApproveRegistrationApplication { + id: app_with_email.id, + approve: true, + deny_reason: None, + }), + context.reset_request_count(), + admin_local_user_view.clone(), + ) + .await; + // Approval should be processed up until email sending is attempted + assert!(approval.is_err_and(|e| e.error_type == LemmyErrorType::NoEmailSetup)); + + expected_unread_applications -= 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // When the application is approved it should only be returned for unread queries + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + assert!( + all_applications.registration_applications[0] + .creator_local_user + .accepted_application + ); + + let (_local_user, app_with_email_2) = signup( + pool, + instance.id, + "user_w_email_2", + Some("lemmy2@localhost"), + ) + .await?; + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // Email not verified, so application still not visible + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + update_site( + Json(EditSite { + require_email_verification: Some(false), + ..Default::default() + }), + context.reset_request_count(), + admin_local_user_view.clone(), + ) + .await?; + + // TODO: There is probably a better way to ensure cache invalidation + tokio::time::sleep(CACHE_DURATION_API).await; + + expected_total_applications += 1; + expected_unread_applications += 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // After disabling email verification the application should now be visible + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + approve_registration_application( + Json(ApproveRegistrationApplication { + id: app_with_email_2.id, + approve: false, + deny_reason: None, + }), + context.reset_request_count(), + admin_local_user_view.clone(), + ) + .await?; + + expected_unread_applications -= 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // Denied applications should not be marked as unread + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + signup(pool, instance.id, "user_wo_email", None).await?; + + expected_total_applications += 1; + expected_unread_applications += 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // New user without email should immediately be visible + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + signup(pool, instance.id, "user_w_email_3", None).await?; + + expected_total_applications += 1; + expected_unread_applications += 1; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // New user with email should immediately be visible + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + update_site( + Json(EditSite { + registration_mode: Some(RegistrationMode::Open), + ..Default::default() + }), + context.reset_request_count(), + admin_local_user_view.clone(), + ) + .await?; + + // TODO: There is probably a better way to ensure cache invalidation + tokio::time::sleep(CACHE_DURATION_API).await; + + let (application_count, unread_applications, all_applications) = + get_application_statuses(&context, admin_local_user_view.clone()).await?; + + // TODO: At this time applications do not get approved when switching to open registration, so the + // numbers will not change. See https://github.com/LemmyNet/lemmy/issues/4969 + // expected_application_count = 0; + // expected_unread_applications_len = 0; + + // When applications are not required all previous applications should become approved but still + // visible + assert_eq!( + application_count.registration_applications, + i64::from(expected_unread_applications), + ); + assert_eq!( + unread_applications.registration_applications.len(), + usize::from(expected_unread_applications), + ); + assert_eq!( + all_applications.registration_applications.len(), + expected_total_applications, + ); + + LocalSite::delete(pool).await?; + // Instance deletion cascades cleanup of all created persons + Instance::delete(pool, instance.id).await?; + + Ok(()) +} diff --git a/crates/api/src/site/registration_applications/unread_count.rs b/crates/api/src/site/registration_applications/unread_count.rs index a12ecb1d3..5cc391ed0 100644 --- a/crates/api/src/site/registration_applications/unread_count.rs +++ b/crates/api/src/site/registration_applications/unread_count.rs @@ -1,4 +1,5 @@ -use actix_web::web::{Data, Json}; +use activitypub_federation::config::Data; +use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, site::GetUnreadRegistrationApplicationCountResponse, diff --git a/crates/api_crud/src/site/create.rs b/crates/api_crud/src/site/create.rs index 6b1909966..9dcd1595a 100644 --- a/crates/api_crud/src/site/create.rs +++ b/crates/api_crud/src/site/create.rs @@ -1,6 +1,6 @@ use crate::site::{application_question_check, site_default_post_listing_type_check}; -use activitypub_federation::http_signatures::generate_actor_keypair; -use actix_web::web::{Data, Json}; +use activitypub_federation::{config::Data, http_signatures::generate_actor_keypair}; +use actix_web::web::Json; use lemmy_api_common::{ context::LemmyContext, site::{CreateSite, SiteResponse}, From 254ef6dab371228367d4c3556be40d0050017546 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 13 Aug 2024 16:53:05 -0400 Subject: [PATCH 57/69] Make site metadata fetch endpoint require auth. (#4968) * Make site metadata fetch require auth. * Update crates/api/src/post/get_link_metadata.rs Co-authored-by: dullbananas --------- Co-authored-by: dullbananas --- crates/api/src/post/get_link_metadata.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/crates/api/src/post/get_link_metadata.rs b/crates/api/src/post/get_link_metadata.rs index 0669408aa..e469b51c7 100644 --- a/crates/api/src/post/get_link_metadata.rs +++ b/crates/api/src/post/get_link_metadata.rs @@ -4,6 +4,7 @@ use lemmy_api_common::{ post::{GetSiteMetadata, GetSiteMetadataResponse}, request::fetch_link_metadata, }; +use lemmy_db_views::structs::LocalUserView; use lemmy_utils::{ error::{LemmyErrorExt, LemmyResult}, LemmyErrorType, @@ -14,6 +15,8 @@ use url::Url; pub async fn get_link_metadata( data: Query, context: Data, + // Require an account for this API + _local_user_view: LocalUserView, ) -> LemmyResult> { let url = Url::parse(&data.url).with_lemmy_type(LemmyErrorType::InvalidUrl)?; let metadata = fetch_link_metadata(&url, &context).await?; From 76a2c6e79b19d8bf44a563d492bff8459703596b Mon Sep 17 00:00:00 2001 From: Richard Schwab Date: Wed, 14 Aug 2024 00:54:56 +0200 Subject: [PATCH 58/69] Fix scheduled task to delete users with denied applications (#4907) After an admin interacted with an application it can only be accepted or denied. Denial reasons are not required by Lemmys backend, even though they're mandatory in Lemmy-UI, and therefore they are not a reliable indicator of an application being denied. This aligns the cleanup logic with the logic used for the unread application count. --- crates/db_schema/src/impls/local_user.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/db_schema/src/impls/local_user.rs b/crates/db_schema/src/impls/local_user.rs index 32e8d50b7..acff6af2a 100644 --- a/crates/db_schema/src/impls/local_user.rs +++ b/crates/db_schema/src/impls/local_user.rs @@ -115,11 +115,11 @@ impl LocalUser { let conn = &mut get_conn(pool).await?; // Make sure: - // - The deny reason exists + // - An admin has interacted with the application // - The app is older than a week // - The accepted_application is false let old_denied_registrations = registration_application::table - .filter(registration_application::deny_reason.is_not_null()) + .filter(registration_application::admin_id.is_not_null()) .filter(registration_application::published.lt(now() - 1.week())) .select(registration_application::local_user_id); From 6b9e5ecb4809c7de6852f5eaa326abdd6984ba07 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Thu, 15 Aug 2024 08:50:27 -0400 Subject: [PATCH 59/69] Version 0.19.6-beta.5 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a53843f6e..8a0fddff1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,7 +2804,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2834,7 +2834,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2871,7 +2871,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "accept-language", "activitypub_federation", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "anyhow", "clap", @@ -2945,7 +2945,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "anyhow", @@ -2984,7 +2984,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "actix-web", "chrono", @@ -3006,7 +3006,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "chrono", "diesel", @@ -3026,7 +3026,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "diesel", "diesel-async", @@ -3038,7 +3038,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -3069,7 +3069,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-web", @@ -3093,7 +3093,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "activitypub_federation", "actix-cors", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 228ff69f1..12047ea09 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.6-beta.4" +version = "0.19.6-beta.5" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.6-beta.4", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.6-beta.4", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.6-beta.4", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.6-beta.4", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.6-beta.4", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.6-beta.4", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.6-beta.4", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.6-beta.4", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.6-beta.4", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.6-beta.4", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.6-beta.4", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.5", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.5", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.5", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.5", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.5", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.5", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.5", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.5", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.5", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.5", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.5", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index 179f68843..8fad50afb 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit 179f6884398d3536d16382df5dc40da4e47835aa +Subproject commit 8fad50afb7bdaf1ffec80b5d97c266ed2dc3f209 From 2913cdf556d64bfaac63c585a99d71c005f0b6aa Mon Sep 17 00:00:00 2001 From: Dessalines Date: Mon, 19 Aug 2024 19:44:13 -0400 Subject: [PATCH 60/69] Version 0.19.6-beta.6 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 8a0fddff1..e2265a639 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,7 +2804,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-web", @@ -2834,7 +2834,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-web", @@ -2871,7 +2871,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "accept-language", "activitypub_federation", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-web", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "anyhow", "clap", @@ -2945,7 +2945,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "anyhow", @@ -2984,7 +2984,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "actix-web", "chrono", @@ -3006,7 +3006,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "chrono", "diesel", @@ -3026,7 +3026,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "diesel", "diesel-async", @@ -3038,7 +3038,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-web", @@ -3069,7 +3069,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-web", @@ -3093,7 +3093,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "activitypub_federation", "actix-cors", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 12047ea09..dcd389186 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.6-beta.5" +version = "0.19.6-beta.6" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.6-beta.5", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.6-beta.5", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.6-beta.5", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.6-beta.5", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.6-beta.5", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.6-beta.5", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.6-beta.5", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.6-beta.5", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.6-beta.5", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.6-beta.5", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.6-beta.5", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.6", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.6", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.6", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.6", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.6", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.6", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.6", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.6", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.6", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.6", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.6", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index 8fad50afb..bc9b53057 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit 8fad50afb7bdaf1ffec80b5d97c266ed2dc3f209 +Subproject commit bc9b5305769900c5a59d8f139f110e004085f92b From bd1b7aa6ef27591fbcbd2b8d04d3b2c03cc0d3c5 Mon Sep 17 00:00:00 2001 From: flamingos-cant <45780476+flamingo-cant-draw@users.noreply.github.com> Date: Tue, 20 Aug 2024 15:16:14 +0100 Subject: [PATCH 61/69] Let federation modify groups (#4937) * Don't check if group is local * Add API test for mods modifying communities --- api_tests/src/community.spec.ts | 40 +++++++++++++++++++++++ crates/apub/src/protocol/objects/group.rs | 3 +- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/api_tests/src/community.spec.ts b/api_tests/src/community.spec.ts index d172f7045..d8aa6cad6 100644 --- a/api_tests/src/community.spec.ts +++ b/api_tests/src/community.spec.ts @@ -1,5 +1,6 @@ jest.setTimeout(120000); +import { AddModToCommunity } from "lemmy-js-client/dist/types/AddModToCommunity"; import { CommunityView } from "lemmy-js-client/dist/types/CommunityView"; import { alpha, @@ -9,6 +10,7 @@ import { resolveCommunity, createCommunity, deleteCommunity, + delay, removeCommunity, getCommunity, followCommunity, @@ -533,3 +535,41 @@ test("Content in local-only community doesn't federate", async () => { Error("couldnt_find_object"), ); }); + +test("Remote mods can edit communities", async () => { + let communityRes = await createCommunity(alpha); + + let betaCommunity = await resolveCommunity( + beta, + communityRes.community_view.community.actor_id, + ); + if (!betaCommunity.community) { + throw "Missing beta community"; + } + let betaOnAlpha = await resolvePerson(alpha, "lemmy_beta@lemmy-beta:8551"); + + let form: AddModToCommunity = { + community_id: communityRes.community_view.community.id, + person_id: betaOnAlpha.person?.person.id as number, + added: true, + }; + alpha.addModToCommunity(form); + + let form2: EditCommunity = { + community_id: betaCommunity.community?.community.id as number, + description: "Example description", + }; + + await editCommunity(beta, form2); + // give alpha time to get and process the edit + await delay(1000); + + let alphaCommunity = await getCommunity( + alpha, + communityRes.community_view.community.id, + ); + + await expect(alphaCommunity.community_view.community.description).toBe( + "Example description", + ); +}); diff --git a/crates/apub/src/protocol/objects/group.rs b/crates/apub/src/protocol/objects/group.rs index a95fff262..8f138e001 100644 --- a/crates/apub/src/protocol/objects/group.rs +++ b/crates/apub/src/protocol/objects/group.rs @@ -7,7 +7,7 @@ use crate::{ community_outbox::ApubCommunityOutbox, }, local_site_data_cached, - objects::{community::ApubCommunity, read_from_string_or_source_opt, verify_is_remote_object}, + objects::{community::ApubCommunity, read_from_string_or_source_opt}, protocol::{ objects::{Endpoints, LanguageTag}, ImageObject, @@ -80,7 +80,6 @@ impl Group { ) -> LemmyResult<()> { check_apub_id_valid_with_strictness(self.id.inner(), true, context).await?; verify_domains_match(expected_domain, self.id.inner())?; - verify_is_remote_object(&self.id, context)?; let local_site_data = local_site_data_cached(&mut context.pool()).await?; let slur_regex = &local_site_opt_to_slur_regex(&local_site_data.local_site); From 101476df872d58e2082a74daa659ee3582baa763 Mon Sep 17 00:00:00 2001 From: dullbananas Date: Thu, 22 Aug 2024 08:33:00 -0700 Subject: [PATCH 62/69] Make scripts work in path that contains spaces (#4986) --- scripts/db_perf.sh | 2 +- scripts/dump_schema.sh | 2 +- scripts/lint.sh | 2 +- scripts/release.sh | 2 +- scripts/sql_format_check.sh | 2 +- scripts/test-with-coverage.sh | 2 +- scripts/test.sh | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/scripts/db_perf.sh b/scripts/db_perf.sh index ef4b2751a..1d53e0d37 100755 --- a/scripts/db_perf.sh +++ b/scripts/db_perf.sh @@ -6,7 +6,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" source scripts/start_dev_db.sh diff --git a/scripts/dump_schema.sh b/scripts/dump_schema.sh index f783be26b..c32cf20e5 100755 --- a/scripts/dump_schema.sh +++ b/scripts/dump_schema.sh @@ -5,7 +5,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" source scripts/start_dev_db.sh diff --git a/scripts/lint.sh b/scripts/lint.sh index 20d89acb4..c9f0f5dd7 100755 --- a/scripts/lint.sh +++ b/scripts/lint.sh @@ -3,7 +3,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" # Format rust files cargo +nightly fmt diff --git a/scripts/release.sh b/scripts/release.sh index 1cf7b168a..79209f3b4 100755 --- a/scripts/release.sh +++ b/scripts/release.sh @@ -8,7 +8,7 @@ third_semver=$(echo $new_tag | cut -d "." -f 3) # Goto the upper route CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" # The docker installs should only update for non release-candidates # IE, when the third semver is a number, not '2-rc' diff --git a/scripts/sql_format_check.sh b/scripts/sql_format_check.sh index fabc3b3ed..3a2710b84 100755 --- a/scripts/sql_format_check.sh +++ b/scripts/sql_format_check.sh @@ -5,7 +5,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" # Copy the files to a temp dir TMP_DIR=$(mktemp -d) diff --git a/scripts/test-with-coverage.sh b/scripts/test-with-coverage.sh index e4dfcddf8..7a4905b8e 100755 --- a/scripts/test-with-coverage.sh +++ b/scripts/test-with-coverage.sh @@ -3,7 +3,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" PACKAGE="$1" echo "$PACKAGE" diff --git a/scripts/test.sh b/scripts/test.sh index 04cc94f9d..e08148db0 100755 --- a/scripts/test.sh +++ b/scripts/test.sh @@ -3,7 +3,7 @@ set -e CWD="$(cd -P -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd -P)" -cd $CWD/../ +cd "$CWD/../" PACKAGE="$1" TEST="$2" From d479bb96c64047a84914d64cbe1d8a366e1ec182 Mon Sep 17 00:00:00 2001 From: Dessalines Date: Tue, 27 Aug 2024 16:32:08 -0400 Subject: [PATCH 63/69] Version 0.19.6-beta.7 --- Cargo.lock | 26 +++++++++++++------------- Cargo.toml | 24 ++++++++++++------------ crates/utils/translations | 2 +- 3 files changed, 26 insertions(+), 26 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e2265a639..011a9fbac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2804,7 +2804,7 @@ checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55" [[package]] name = "lemmy_api" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-web", @@ -2834,7 +2834,7 @@ dependencies = [ [[package]] name = "lemmy_api_common" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-web", @@ -2871,7 +2871,7 @@ dependencies = [ [[package]] name = "lemmy_api_crud" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "accept-language", "activitypub_federation", @@ -2893,7 +2893,7 @@ dependencies = [ [[package]] name = "lemmy_apub" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-web", @@ -2930,7 +2930,7 @@ dependencies = [ [[package]] name = "lemmy_db_perf" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "anyhow", "clap", @@ -2945,7 +2945,7 @@ dependencies = [ [[package]] name = "lemmy_db_schema" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "anyhow", @@ -2984,7 +2984,7 @@ dependencies = [ [[package]] name = "lemmy_db_views" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "actix-web", "chrono", @@ -3006,7 +3006,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_actor" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "chrono", "diesel", @@ -3026,7 +3026,7 @@ dependencies = [ [[package]] name = "lemmy_db_views_moderator" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "diesel", "diesel-async", @@ -3038,7 +3038,7 @@ dependencies = [ [[package]] name = "lemmy_federate" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-web", @@ -3069,7 +3069,7 @@ dependencies = [ [[package]] name = "lemmy_routes" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-web", @@ -3093,7 +3093,7 @@ dependencies = [ [[package]] name = "lemmy_server" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "activitypub_federation", "actix-cors", @@ -3137,7 +3137,7 @@ dependencies = [ [[package]] name = "lemmy_utils" -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" dependencies = [ "actix-web", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index dcd389186..2501efe7c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,5 +1,5 @@ [workspace.package] -version = "0.19.6-beta.6" +version = "0.19.6-beta.7" edition = "2021" description = "A link aggregator for the fediverse" license = "AGPL-3.0" @@ -89,17 +89,17 @@ unwrap_used = "deny" unimplemented = "deny" [workspace.dependencies] -lemmy_api = { version = "=0.19.6-beta.6", path = "./crates/api" } -lemmy_api_crud = { version = "=0.19.6-beta.6", path = "./crates/api_crud" } -lemmy_apub = { version = "=0.19.6-beta.6", path = "./crates/apub" } -lemmy_utils = { version = "=0.19.6-beta.6", path = "./crates/utils", default-features = false } -lemmy_db_schema = { version = "=0.19.6-beta.6", path = "./crates/db_schema" } -lemmy_api_common = { version = "=0.19.6-beta.6", path = "./crates/api_common" } -lemmy_routes = { version = "=0.19.6-beta.6", path = "./crates/routes" } -lemmy_db_views = { version = "=0.19.6-beta.6", path = "./crates/db_views" } -lemmy_db_views_actor = { version = "=0.19.6-beta.6", path = "./crates/db_views_actor" } -lemmy_db_views_moderator = { version = "=0.19.6-beta.6", path = "./crates/db_views_moderator" } -lemmy_federate = { version = "=0.19.6-beta.6", path = "./crates/federate" } +lemmy_api = { version = "=0.19.6-beta.7", path = "./crates/api" } +lemmy_api_crud = { version = "=0.19.6-beta.7", path = "./crates/api_crud" } +lemmy_apub = { version = "=0.19.6-beta.7", path = "./crates/apub" } +lemmy_utils = { version = "=0.19.6-beta.7", path = "./crates/utils", default-features = false } +lemmy_db_schema = { version = "=0.19.6-beta.7", path = "./crates/db_schema" } +lemmy_api_common = { version = "=0.19.6-beta.7", path = "./crates/api_common" } +lemmy_routes = { version = "=0.19.6-beta.7", path = "./crates/routes" } +lemmy_db_views = { version = "=0.19.6-beta.7", path = "./crates/db_views" } +lemmy_db_views_actor = { version = "=0.19.6-beta.7", path = "./crates/db_views_actor" } +lemmy_db_views_moderator = { version = "=0.19.6-beta.7", path = "./crates/db_views_moderator" } +lemmy_federate = { version = "=0.19.6-beta.7", path = "./crates/federate" } activitypub_federation = { version = "0.5.8", default-features = false, features = [ "actix-web", ] } diff --git a/crates/utils/translations b/crates/utils/translations index bc9b53057..7adddded5 160000 --- a/crates/utils/translations +++ b/crates/utils/translations @@ -1 +1 @@ -Subproject commit bc9b5305769900c5a59d8f139f110e004085f92b +Subproject commit 7adddded581fcd965ab33b91c5fe10e0d7247208 From ae3df4db728b5087ffc259495282982ea60545fb Mon Sep 17 00:00:00 2001 From: Joseph Silva Date: Sat, 31 Aug 2024 19:36:47 -0700 Subject: [PATCH 64/69] Replace "post" with "comment" in comment_report_view.rs (#4989) --- crates/db_views/src/comment_report_view.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/db_views/src/comment_report_view.rs b/crates/db_views/src/comment_report_view.rs index d7b26a1ed..1866aaee9 100644 --- a/crates/db_views/src/comment_report_view.rs +++ b/crates/db_views/src/comment_report_view.rs @@ -196,7 +196,7 @@ impl CommentReportView { queries().read(pool, (report_id, my_person_id)).await } - /// Returns the current unresolved post report count for the communities you mod + /// Returns the current unresolved comment report count for the communities you mod pub async fn get_report_count( pool: &mut DbPool<'_>, my_person_id: PersonId, From fa94a5869e95737e9b6c91458dc4f7f36338a851 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 03:11:01 +0000 Subject: [PATCH 65/69] chore(deps): update dependency eslint to v9.9.1 (#4992) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 140 +++++++++++++++++++-------------------- 1 file changed, 69 insertions(+), 71 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 3da842f5d..1b962d3e8 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -16,16 +16,16 @@ importers: version: 22.0.2 '@typescript-eslint/eslint-plugin': specifier: ^8.0.0 - version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4) + version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4) '@typescript-eslint/parser': specifier: ^8.0.0 - version: 8.0.0(eslint@9.8.0)(typescript@5.5.4) + version: 8.0.0(eslint@9.9.1)(typescript@5.5.4) eslint: specifier: ^9.8.0 - version: 9.8.0 + version: 9.9.1 eslint-plugin-prettier: specifier: ^5.1.3 - version: 5.2.1(eslint@9.8.0)(prettier@3.3.3) + version: 5.2.1(eslint@9.9.1)(prettier@3.3.3) jest: specifier: ^29.5.0 version: 29.7.0(@types/node@22.0.2) @@ -43,14 +43,10 @@ importers: version: 5.5.4 typescript-eslint: specifier: ^8.0.0 - version: 8.0.0(eslint@9.8.0)(typescript@5.5.4) + version: 8.0.0(eslint@9.9.1)(typescript@5.5.4) packages: - '@aashutoshrathi/word-wrap@1.2.6': - resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} - engines: {node: '>=0.10.0'} - '@ampproject/remapping@2.2.1': resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} engines: {node: '>=6.0.0'} @@ -232,16 +228,16 @@ packages: resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} - '@eslint/config-array@0.17.1': - resolution: {integrity: sha512-BlYOpej8AQ8Ev9xVqroV7a02JK3SkBAaN9GfMMH9W6Ch8FlQlkjGw4Ir7+FgYwfirivAf4t+GtzuAxqfukmISA==} + '@eslint/config-array@0.18.0': + resolution: {integrity: sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/eslintrc@3.1.0': resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - '@eslint/js@9.8.0': - resolution: {integrity: sha512-MfluB7EUfxXtv3i/++oh89uzAr4PDI4nn201hsp+qaXqsjAWzinlZEHEfPgAX4doIlKvPG/i0A9dpKxOLII8yA==} + '@eslint/js@9.9.1': + resolution: {integrity: sha512-xIDQRsfg5hNBqHz04H1R3scSVwmI+KUbqjsQKHKQ1DAUSaUjYPReZZmS/5PNiKu1fUvzDd6H7DEDKACSEhu+TQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} '@eslint/object-schema@2.1.4': @@ -649,15 +645,6 @@ packages: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} - debug@4.3.4: - resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} - engines: {node: '>=6.0'} - peerDependencies: - supports-color: '*' - peerDependenciesMeta: - supports-color: - optional: true - debug@4.3.6: resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} engines: {node: '>=6.0'} @@ -754,10 +741,15 @@ packages: resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} - eslint@9.8.0: - resolution: {integrity: sha512-K8qnZ/QJzT2dLKdZJVX6W4XOwBzutMYmt0lqUS+JdXgd+HTYFlonFgkJ8s44d/zMPPCnOOk0kMWCApCPhiOy9A==} + eslint@9.9.1: + resolution: {integrity: sha512-dHvhrbfr4xFQ9/dq+jcVneZMyRYLjggWjk6RVsIiHsP8Rz6yZ8LvZ//iU4TrZF+SXWG+JkNF2OyiZRvzgRDqMg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + peerDependencies: + jiti: '*' + peerDependenciesMeta: + jiti: + optional: true espree@10.1.0: resolution: {integrity: sha512-M1M6CpiE6ffoigIOWYO9UDP8TMUw9kqb21tf+08IgDYjCsOvCuDt4jQcZmoYxx+w7zlKw9/N0KXfto+I8/FrXA==} @@ -768,8 +760,8 @@ packages: engines: {node: '>=4'} hasBin: true - esquery@1.5.0: - resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + esquery@1.6.0: + resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} esrecurse@4.3.0: @@ -928,6 +920,10 @@ packages: resolution: {integrity: sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==} engines: {node: '>= 4'} + ignore@5.3.2: + resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} + engines: {node: '>= 4'} + import-fresh@3.3.0: resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} engines: {node: '>=6'} @@ -1281,8 +1277,8 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} - optionator@0.9.3: - resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + optionator@0.9.4: + resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} p-limit@2.3.0: @@ -1603,6 +1599,10 @@ packages: engines: {node: '>= 8'} hasBin: true + word-wrap@1.2.5: + resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} + engines: {node: '>=0.10.0'} + wrap-ansi@7.0.0: resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} engines: {node: '>=10'} @@ -1635,8 +1635,6 @@ packages: snapshots: - '@aashutoshrathi/word-wrap@1.2.6': {} - '@ampproject/remapping@2.2.1': dependencies: '@jridgewell/gen-mapping': 0.3.3 @@ -1841,17 +1839,17 @@ snapshots: '@bcoe/v8-coverage@0.2.3': {} - '@eslint-community/eslint-utils@4.4.0(eslint@9.8.0)': + '@eslint-community/eslint-utils@4.4.0(eslint@9.9.1)': dependencies: - eslint: 9.8.0 + eslint: 9.9.1 eslint-visitor-keys: 3.4.3 '@eslint-community/regexpp@4.11.0': {} - '@eslint/config-array@0.17.1': + '@eslint/config-array@0.18.0': dependencies: '@eslint/object-schema': 2.1.4 - debug: 4.3.4 + debug: 4.3.6 minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -1859,10 +1857,10 @@ snapshots: '@eslint/eslintrc@3.1.0': dependencies: ajv: 6.12.6 - debug: 4.3.4 + debug: 4.3.6 espree: 10.1.0 globals: 14.0.0 - ignore: 5.3.1 + ignore: 5.3.2 import-fresh: 3.3.0 js-yaml: 4.1.0 minimatch: 3.1.2 @@ -1870,7 +1868,7 @@ snapshots: transitivePeerDependencies: - supports-color - '@eslint/js@9.8.0': {} + '@eslint/js@9.9.1': {} '@eslint/object-schema@2.1.4': {} @@ -2143,15 +2141,15 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/parser': 8.0.0(eslint@9.9.1)(typescript@5.5.4) '@typescript-eslint/scope-manager': 8.0.0 - '@typescript-eslint/type-utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/type-utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 - eslint: 9.8.0 + eslint: 9.9.1 graphemer: 1.4.0 ignore: 5.3.1 natural-compare: 1.4.0 @@ -2161,14 +2159,14 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4)': + '@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 8.0.0 debug: 4.3.6 - eslint: 9.8.0 + eslint: 9.9.1 optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -2179,10 +2177,10 @@ snapshots: '@typescript-eslint/types': 8.0.0 '@typescript-eslint/visitor-keys': 8.0.0 - '@typescript-eslint/type-utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.0.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4) debug: 4.3.6 ts-api-utils: 1.3.0(typescript@5.5.4) optionalDependencies: @@ -2208,13 +2206,13 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.0.0(eslint@9.8.0)(typescript@5.5.4)': + '@typescript-eslint/utils@8.0.0(eslint@9.9.1)(typescript@5.5.4)': dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) '@typescript-eslint/scope-manager': 8.0.0 '@typescript-eslint/types': 8.0.0 '@typescript-eslint/typescript-estree': 8.0.0(typescript@5.5.4) - eslint: 9.8.0 + eslint: 9.9.1 transitivePeerDependencies: - supports-color - typescript @@ -2428,10 +2426,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - debug@4.3.4: - dependencies: - ms: 2.1.2 - debug@4.3.6: dependencies: ms: 2.1.2 @@ -2472,9 +2466,9 @@ snapshots: escape-string-regexp@4.0.0: {} - eslint-plugin-prettier@5.2.1(eslint@9.8.0)(prettier@3.3.3): + eslint-plugin-prettier@5.2.1(eslint@9.9.1)(prettier@3.3.3): dependencies: - eslint: 9.8.0 + eslint: 9.9.1 prettier: 3.3.3 prettier-linter-helpers: 1.0.0 synckit: 0.9.1 @@ -2488,31 +2482,31 @@ snapshots: eslint-visitor-keys@4.0.0: {} - eslint@9.8.0: + eslint@9.9.1: dependencies: - '@eslint-community/eslint-utils': 4.4.0(eslint@9.8.0) + '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1) '@eslint-community/regexpp': 4.11.0 - '@eslint/config-array': 0.17.1 + '@eslint/config-array': 0.18.0 '@eslint/eslintrc': 3.1.0 - '@eslint/js': 9.8.0 + '@eslint/js': 9.9.1 '@humanwhocodes/module-importer': 1.0.1 '@humanwhocodes/retry': 0.3.0 '@nodelib/fs.walk': 1.2.8 ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4 + debug: 4.3.6 escape-string-regexp: 4.0.0 eslint-scope: 8.0.2 eslint-visitor-keys: 4.0.0 espree: 10.1.0 - esquery: 1.5.0 + esquery: 1.6.0 esutils: 2.0.3 fast-deep-equal: 3.1.3 file-entry-cache: 8.0.0 find-up: 5.0.0 glob-parent: 6.0.2 - ignore: 5.3.1 + ignore: 5.3.2 imurmurhash: 0.1.4 is-glob: 4.0.3 is-path-inside: 3.0.3 @@ -2521,7 +2515,7 @@ snapshots: lodash.merge: 4.6.2 minimatch: 3.1.2 natural-compare: 1.4.0 - optionator: 0.9.3 + optionator: 0.9.4 strip-ansi: 6.0.1 text-table: 0.2.0 transitivePeerDependencies: @@ -2535,7 +2529,7 @@ snapshots: esprima@4.0.1: {} - esquery@1.5.0: + esquery@1.6.0: dependencies: estraverse: 5.3.0 @@ -2667,7 +2661,7 @@ snapshots: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.3.2 - ignore: 5.3.1 + ignore: 5.3.2 merge2: 1.4.1 slash: 3.0.0 @@ -2689,6 +2683,8 @@ snapshots: ignore@5.3.1: {} + ignore@5.3.2: {} + import-fresh@3.3.0: dependencies: parent-module: 1.0.1 @@ -3204,14 +3200,14 @@ snapshots: dependencies: mimic-fn: 2.1.0 - optionator@0.9.3: + optionator@0.9.4: dependencies: - '@aashutoshrathi/word-wrap': 1.2.6 deep-is: 0.1.4 fast-levenshtein: 2.0.6 levn: 0.4.1 prelude-ls: 1.2.1 type-check: 0.4.0 + word-wrap: 1.2.5 p-limit@2.3.0: dependencies: @@ -3433,11 +3429,11 @@ snapshots: type-fest@0.21.3: {} - typescript-eslint@8.0.0(eslint@9.8.0)(typescript@5.5.4): + typescript-eslint@8.0.0(eslint@9.9.1)(typescript@5.5.4): dependencies: - '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.8.0)(typescript@5.5.4))(eslint@9.8.0)(typescript@5.5.4) - '@typescript-eslint/parser': 8.0.0(eslint@9.8.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.0.0(eslint@9.8.0)(typescript@5.5.4) + '@typescript-eslint/eslint-plugin': 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/parser': 8.0.0(eslint@9.9.1)(typescript@5.5.4) + '@typescript-eslint/utils': 8.0.0(eslint@9.9.1)(typescript@5.5.4) optionalDependencies: typescript: 5.5.4 transitivePeerDependencies: @@ -3472,6 +3468,8 @@ snapshots: dependencies: isexe: 2.0.0 + word-wrap@1.2.5: {} + wrap-ansi@7.0.0: dependencies: ansi-styles: 4.3.0 From f617227f0d096905e86577070226342b93975d16 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 06:41:42 +0000 Subject: [PATCH 66/69] chore(deps): update dependency ts-jest to v29.2.5 (#4990) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 25 +++++++++---------------- 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 1b962d3e8..97d5738da 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -37,7 +37,7 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4) + version: 29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -512,8 +512,8 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} - async@3.2.5: - resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + async@3.2.6: + resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} babel-jest@29.7.0: resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} @@ -1412,11 +1412,6 @@ packages: resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} hasBin: true - semver@7.6.2: - resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} - engines: {node: '>=10'} - hasBin: true - semver@7.6.3: resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} engines: {node: '>=10'} @@ -1522,8 +1517,8 @@ packages: peerDependencies: typescript: '>=4.2.0' - ts-jest@29.2.4: - resolution: {integrity: sha512-3d6tgDyhCI29HlpwIq87sNuI+3Q6GLTTCeYRHCs7vDz+/3GCMwEtV9jezLyl4ZtnBgx00I7hm8PCP8cTksMGrw==} + ts-jest@29.2.5: + resolution: {integrity: sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==} engines: {node: ^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0} hasBin: true peerDependencies: @@ -2264,7 +2259,7 @@ snapshots: array-union@2.1.0: {} - async@3.2.5: {} + async@3.2.6: {} babel-jest@29.7.0(@babel/core@7.23.9): dependencies: @@ -2771,7 +2766,7 @@ snapshots: jake@10.9.2: dependencies: - async: 3.2.5 + async: 3.2.6 chalk: 4.1.2 filelist: 1.0.4 minimatch: 3.1.2 @@ -3032,7 +3027,7 @@ snapshots: jest-util: 29.7.0 natural-compare: 1.4.0 pretty-format: 29.7.0 - semver: 7.6.2 + semver: 7.6.3 transitivePeerDependencies: - supports-color @@ -3311,8 +3306,6 @@ snapshots: semver@6.3.1: {} - semver@7.6.2: {} - semver@7.6.3: {} shebang-command@2.0.0: @@ -3400,7 +3393,7 @@ snapshots: dependencies: typescript: 5.5.4 - ts-jest@29.2.4(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4): + ts-jest@29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 From b1afd98d29efa3b18973f03821dbfa4aa126e433 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 09:40:23 +0000 Subject: [PATCH 67/69] chore(deps): update dependency @types/node to v22.5.1 (#4991) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/pnpm-lock.yaml | 76 ++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/api_tests/pnpm-lock.yaml b/api_tests/pnpm-lock.yaml index 97d5738da..3b1970681 100644 --- a/api_tests/pnpm-lock.yaml +++ b/api_tests/pnpm-lock.yaml @@ -13,7 +13,7 @@ importers: version: 29.5.12 '@types/node': specifier: ^22.0.2 - version: 22.0.2 + version: 22.5.1 '@typescript-eslint/eslint-plugin': specifier: ^8.0.0 version: 8.0.0(@typescript-eslint/parser@8.0.0(eslint@9.9.1)(typescript@5.5.4))(eslint@9.9.1)(typescript@5.5.4) @@ -28,7 +28,7 @@ importers: version: 5.2.1(eslint@9.9.1)(prettier@3.3.3) jest: specifier: ^29.5.0 - version: 29.7.0(@types/node@22.0.2) + version: 29.7.0(@types/node@22.5.1) lemmy-js-client: specifier: 0.19.5-alpha.1 version: 0.19.5-alpha.1 @@ -37,7 +37,7 @@ importers: version: 3.3.3 ts-jest: specifier: ^29.1.0 - version: 29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4) + version: 29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.5.1))(typescript@5.5.4) typescript: specifier: ^5.5.4 version: 5.5.4 @@ -396,8 +396,8 @@ packages: '@types/jest@29.5.12': resolution: {integrity: sha512-eDC8bTvT/QhYdxJAulQikueigY5AsdBRH2yDKW3yveW7svY3+DzN84/2NUgkw10RTiJbWqZrTtoGVdYlvFJdLw==} - '@types/node@22.0.2': - resolution: {integrity: sha512-yPL6DyFwY5PiMVEwymNeqUTKsDczQBJ/5T7W/46RwLU/VH+AA8aT5TZkvBviLKLbbm0hlfftEkGrNzfRk/fofQ==} + '@types/node@22.5.1': + resolution: {integrity: sha512-KkHsxej0j9IW1KKOOAA/XBA0z08UFSrRQHErzEfA3Vgq57eXIMYboIlHJuYIfd+lwCQjtKqUu3UnmKbtUc9yRw==} '@types/stack-utils@2.0.3': resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} @@ -1570,8 +1570,8 @@ packages: engines: {node: '>=14.17'} hasBin: true - undici-types@6.11.1: - resolution: {integrity: sha512-mIDEX2ek50x0OlRgxryxsenE5XaQD4on5U2inY7RApK3SOJpofyw7uW2AyfMKkhAxXIceo2DeWGVGwyvng1GNQ==} + undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} update-browserslist-db@1.0.13: resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} @@ -1884,7 +1884,7 @@ snapshots: '@jest/console@29.7.0': dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 jest-message-util: 29.7.0 jest-util: 29.7.0 @@ -1897,14 +1897,14 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 ansi-escapes: 4.3.2 chalk: 4.1.2 ci-info: 3.9.0 exit: 0.1.2 graceful-fs: 4.2.11 jest-changed-files: 29.7.0 - jest-config: 29.7.0(@types/node@22.0.2) + jest-config: 29.7.0(@types/node@22.5.1) jest-haste-map: 29.7.0 jest-message-util: 29.7.0 jest-regex-util: 29.6.3 @@ -1929,7 +1929,7 @@ snapshots: dependencies: '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 jest-mock: 29.7.0 '@jest/expect-utils@29.7.0': @@ -1947,7 +1947,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@sinonjs/fake-timers': 10.3.0 - '@types/node': 22.0.2 + '@types/node': 22.5.1 jest-message-util: 29.7.0 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -1969,7 +1969,7 @@ snapshots: '@jest/transform': 29.7.0 '@jest/types': 29.6.3 '@jridgewell/trace-mapping': 0.3.22 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 collect-v8-coverage: 1.0.2 exit: 0.1.2 @@ -2039,7 +2039,7 @@ snapshots: '@jest/schemas': 29.6.3 '@types/istanbul-lib-coverage': 2.0.6 '@types/istanbul-reports': 3.0.4 - '@types/node': 22.0.2 + '@types/node': 22.5.1 '@types/yargs': 17.0.32 chalk: 4.1.2 @@ -2107,7 +2107,7 @@ snapshots: '@types/graceful-fs@4.1.9': dependencies: - '@types/node': 22.0.2 + '@types/node': 22.5.1 '@types/istanbul-lib-coverage@2.0.6': {} @@ -2124,9 +2124,9 @@ snapshots: expect: 29.7.0 pretty-format: 29.7.0 - '@types/node@22.0.2': + '@types/node@22.5.1': dependencies: - undici-types: 6.11.1 + undici-types: 6.19.8 '@types/stack-utils@2.0.3': {} @@ -2400,13 +2400,13 @@ snapshots: convert-source-map@2.0.0: {} - create-jest@29.7.0(@types/node@22.0.2): + create-jest@29.7.0(@types/node@22.5.1): dependencies: '@jest/types': 29.6.3 chalk: 4.1.2 exit: 0.1.2 graceful-fs: 4.2.11 - jest-config: 29.7.0(@types/node@22.0.2) + jest-config: 29.7.0(@types/node@22.5.1) jest-util: 29.7.0 prompts: 2.4.2 transitivePeerDependencies: @@ -2783,7 +2783,7 @@ snapshots: '@jest/expect': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 co: 4.6.0 dedent: 1.5.1 @@ -2803,16 +2803,16 @@ snapshots: - babel-plugin-macros - supports-color - jest-cli@29.7.0(@types/node@22.0.2): + jest-cli@29.7.0(@types/node@22.5.1): dependencies: '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@22.0.2) + create-jest: 29.7.0(@types/node@22.5.1) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@22.0.2) + jest-config: 29.7.0(@types/node@22.5.1) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -2822,7 +2822,7 @@ snapshots: - supports-color - ts-node - jest-config@29.7.0(@types/node@22.0.2): + jest-config@29.7.0(@types/node@22.5.1): dependencies: '@babel/core': 7.23.9 '@jest/test-sequencer': 29.7.0 @@ -2847,7 +2847,7 @@ snapshots: slash: 3.0.0 strip-json-comments: 3.1.1 optionalDependencies: - '@types/node': 22.0.2 + '@types/node': 22.5.1 transitivePeerDependencies: - babel-plugin-macros - supports-color @@ -2876,7 +2876,7 @@ snapshots: '@jest/environment': 29.7.0 '@jest/fake-timers': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 jest-mock: 29.7.0 jest-util: 29.7.0 @@ -2886,7 +2886,7 @@ snapshots: dependencies: '@jest/types': 29.6.3 '@types/graceful-fs': 4.1.9 - '@types/node': 22.0.2 + '@types/node': 22.5.1 anymatch: 3.1.3 fb-watchman: 2.0.2 graceful-fs: 4.2.11 @@ -2925,7 +2925,7 @@ snapshots: jest-mock@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 jest-util: 29.7.0 jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): @@ -2960,7 +2960,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 emittery: 0.13.1 graceful-fs: 4.2.11 @@ -2988,7 +2988,7 @@ snapshots: '@jest/test-result': 29.7.0 '@jest/transform': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 cjs-module-lexer: 1.2.3 collect-v8-coverage: 1.0.2 @@ -3034,7 +3034,7 @@ snapshots: jest-util@29.7.0: dependencies: '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 chalk: 4.1.2 ci-info: 3.9.0 graceful-fs: 4.2.11 @@ -3053,7 +3053,7 @@ snapshots: dependencies: '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 - '@types/node': 22.0.2 + '@types/node': 22.5.1 ansi-escapes: 4.3.2 chalk: 4.1.2 emittery: 0.13.1 @@ -3062,17 +3062,17 @@ snapshots: jest-worker@29.7.0: dependencies: - '@types/node': 22.0.2 + '@types/node': 22.5.1 jest-util: 29.7.0 merge-stream: 2.0.0 supports-color: 8.1.1 - jest@29.7.0(@types/node@22.0.2): + jest@29.7.0(@types/node@22.5.1): dependencies: '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 - jest-cli: 29.7.0(@types/node@22.0.2) + jest-cli: 29.7.0(@types/node@22.5.1) transitivePeerDependencies: - '@types/node' - babel-plugin-macros @@ -3393,12 +3393,12 @@ snapshots: dependencies: typescript: 5.5.4 - ts-jest@29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.0.2))(typescript@5.5.4): + ts-jest@29.2.5(@babel/core@7.23.9)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.23.9))(jest@29.7.0(@types/node@22.5.1))(typescript@5.5.4): dependencies: bs-logger: 0.2.6 ejs: 3.1.10 fast-json-stable-stringify: 2.1.0 - jest: 29.7.0(@types/node@22.0.2) + jest: 29.7.0(@types/node@22.5.1) jest-util: 29.7.0 json5: 2.2.3 lodash.memoize: 4.1.2 @@ -3435,7 +3435,7 @@ snapshots: typescript@5.5.4: {} - undici-types@6.11.1: {} + undici-types@6.19.8: {} update-browserslist-db@1.0.13(browserslist@4.22.3): dependencies: From 5683d5ed7a414c78f1368273bba4a434be91b8dc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 12:30:05 +0000 Subject: [PATCH 68/69] chore(deps): update pnpm to v9.9.0 (#4994) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- api_tests/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api_tests/package.json b/api_tests/package.json index 4fe5a40bd..bc2d3ec2d 100644 --- a/api_tests/package.json +++ b/api_tests/package.json @@ -6,7 +6,7 @@ "repository": "https://github.com/LemmyNet/lemmy", "author": "Dessalines", "license": "AGPL-3.0", - "packageManager": "pnpm@9.6.0", + "packageManager": "pnpm@9.9.0", "scripts": { "lint": "tsc --noEmit && eslint --report-unused-disable-directives && prettier --check 'src/**/*.ts'", "fix": "prettier --write src && eslint --fix src", From f98b15511a7d8d6fdb0c34c549cfc22441beedef Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 1 Sep 2024 16:47:16 +0000 Subject: [PATCH 69/69] chore(deps): update rust crate derive-new to 0.7.0 (#4995) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 011a9fbac..5dcdd045c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1503,9 +1503,9 @@ dependencies = [ [[package]] name = "derive-new" -version = "0.6.0" +version = "0.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" +checksum = "2cdc8d50f426189eef89dac62fabfa0abb27d5cc008f25bf4156a0203325becc" dependencies = [ "proc-macro2", "quote", diff --git a/Cargo.toml b/Cargo.toml index 2501efe7c..38d4adc5f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -171,7 +171,7 @@ moka = { version = "0.12.8", features = ["future"] } i-love-jesus = { version = "0.1.0" } clap = { version = "4.5.13", features = ["derive", "env"] } pretty_assertions = "1.4.0" -derive-new = "0.6.0" +derive-new = "0.7.0" [dependencies] lemmy_api = { workspace = true }