mirror of
https://github.com/LemmyNet/lemmy.git
synced 2024-06-18 05:10:34 +00:00
Merge branch 'main' into post-thumbnail-background
This commit is contained in:
commit
8d3498d288
|
@ -6,21 +6,23 @@ variables:
|
||||||
- &install_pnpm "corepack enable pnpm"
|
- &install_pnpm "corepack enable pnpm"
|
||||||
- &slow_check_paths
|
- &slow_check_paths
|
||||||
- path:
|
- path:
|
||||||
# rust source code
|
include: [
|
||||||
- "crates/**"
|
# rust source code
|
||||||
- "src/**"
|
"crates/**",
|
||||||
- "**/Cargo.toml"
|
"src/**",
|
||||||
- "Cargo.lock"
|
"**/Cargo.toml",
|
||||||
# database migrations
|
"Cargo.lock",
|
||||||
- "migrations/**"
|
# database migrations
|
||||||
# typescript tests
|
"migrations/**",
|
||||||
- "api_tests/**"
|
# typescript tests
|
||||||
# config files and scripts used by ci
|
"api_tests/**",
|
||||||
- ".woodpecker.yml"
|
# config files and scripts used by ci
|
||||||
- ".rustfmt.toml"
|
".woodpecker.yml",
|
||||||
- "scripts/update_config_defaults.sh"
|
".rustfmt.toml",
|
||||||
- "diesel.toml"
|
"scripts/update_config_defaults.sh",
|
||||||
- ".gitmodules"
|
"diesel.toml",
|
||||||
|
".gitmodules",
|
||||||
|
]
|
||||||
|
|
||||||
# Broken for cron jobs currently, see
|
# Broken for cron jobs currently, see
|
||||||
# https://github.com/woodpecker-ci/woodpecker/issues/1716
|
# https://github.com/woodpecker-ci/woodpecker/issues/1716
|
||||||
|
@ -198,7 +200,7 @@ steps:
|
||||||
- cat target/log/lemmy_*.out || true
|
- cat target/log/lemmy_*.out || true
|
||||||
- "# If you can't see all output, then use the download button"
|
- "# If you can't see all output, then use the download button"
|
||||||
when:
|
when:
|
||||||
status: [failure]
|
- status: [failure]
|
||||||
|
|
||||||
publish_release_docker:
|
publish_release_docker:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
@ -211,7 +213,7 @@ steps:
|
||||||
- RUST_RELEASE_MODE=release
|
- RUST_RELEASE_MODE=release
|
||||||
tag: ${CI_COMMIT_TAG}
|
tag: ${CI_COMMIT_TAG}
|
||||||
when:
|
when:
|
||||||
event: tag
|
- event: tag
|
||||||
|
|
||||||
nightly_build:
|
nightly_build:
|
||||||
image: woodpeckerci/plugin-docker-buildx
|
image: woodpeckerci/plugin-docker-buildx
|
||||||
|
@ -224,7 +226,7 @@ steps:
|
||||||
- RUST_RELEASE_MODE=release
|
- RUST_RELEASE_MODE=release
|
||||||
tag: dev
|
tag: dev
|
||||||
when:
|
when:
|
||||||
event: cron
|
- event: cron
|
||||||
|
|
||||||
# using https://github.com/pksunkara/cargo-workspaces
|
# using https://github.com/pksunkara/cargo-workspaces
|
||||||
publish_to_crates_io:
|
publish_to_crates_io:
|
||||||
|
@ -237,7 +239,7 @@ steps:
|
||||||
- cargo workspaces publish --from-git --allow-dirty --no-verify --allow-branch "${CI_COMMIT_TAG}" --yes custom "${CI_COMMIT_TAG}"
|
- cargo workspaces publish --from-git --allow-dirty --no-verify --allow-branch "${CI_COMMIT_TAG}" --yes custom "${CI_COMMIT_TAG}"
|
||||||
secrets: [cargo_api_token]
|
secrets: [cargo_api_token]
|
||||||
when:
|
when:
|
||||||
event: tag
|
- event: tag
|
||||||
|
|
||||||
notify_on_failure:
|
notify_on_failure:
|
||||||
image: alpine:3
|
image: alpine:3
|
||||||
|
@ -245,7 +247,7 @@ steps:
|
||||||
- apk add curl
|
- apk add curl
|
||||||
- "curl -d'Lemmy CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci"
|
- "curl -d'Lemmy CI build failed: ${CI_PIPELINE_URL}' ntfy.sh/lemmy_drone_ci"
|
||||||
when:
|
when:
|
||||||
status: [failure]
|
- status: [failure]
|
||||||
|
|
||||||
notify_on_tag_deploy:
|
notify_on_tag_deploy:
|
||||||
image: alpine:3
|
image: alpine:3
|
||||||
|
@ -253,7 +255,7 @@ steps:
|
||||||
- apk add curl
|
- apk add curl
|
||||||
- "curl -d'lemmy:${CI_COMMIT_TAG} deployed' ntfy.sh/lemmy_drone_ci"
|
- "curl -d'lemmy:${CI_COMMIT_TAG} deployed' ntfy.sh/lemmy_drone_ci"
|
||||||
when:
|
when:
|
||||||
event: tag
|
- event: tag
|
||||||
|
|
||||||
services:
|
services:
|
||||||
database:
|
database:
|
||||||
|
|
|
@ -27,7 +27,7 @@
|
||||||
"eslint": "^8.57.0",
|
"eslint": "^8.57.0",
|
||||||
"eslint-plugin-prettier": "^5.1.3",
|
"eslint-plugin-prettier": "^5.1.3",
|
||||||
"jest": "^29.5.0",
|
"jest": "^29.5.0",
|
||||||
"lemmy-js-client": "0.19.4-alpha.8",
|
"lemmy-js-client": "0.19.4-alpha.13",
|
||||||
"prettier": "^3.2.5",
|
"prettier": "^3.2.5",
|
||||||
"ts-jest": "^29.1.0",
|
"ts-jest": "^29.1.0",
|
||||||
"typescript": "^5.4.2"
|
"typescript": "^5.4.2"
|
||||||
|
|
|
@ -30,8 +30,8 @@ devDependencies:
|
||||||
specifier: ^29.5.0
|
specifier: ^29.5.0
|
||||||
version: 29.7.0(@types/node@20.11.27)
|
version: 29.7.0(@types/node@20.11.27)
|
||||||
lemmy-js-client:
|
lemmy-js-client:
|
||||||
specifier: 0.19.4-alpha.8
|
specifier: 0.19.4-alpha.13
|
||||||
version: 0.19.4-alpha.8
|
version: 0.19.4-alpha.13
|
||||||
prettier:
|
prettier:
|
||||||
specifier: ^3.2.5
|
specifier: ^3.2.5
|
||||||
version: 3.2.5
|
version: 3.2.5
|
||||||
|
@ -1044,10 +1044,6 @@ packages:
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/asynckit@0.4.0:
|
|
||||||
resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/babel-jest@29.7.0(@babel/core@7.23.9):
|
/babel-jest@29.7.0(@babel/core@7.23.9):
|
||||||
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
|
@ -1261,13 +1257,6 @@ packages:
|
||||||
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/combined-stream@1.0.8:
|
|
||||||
resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==}
|
|
||||||
engines: {node: '>= 0.8'}
|
|
||||||
dependencies:
|
|
||||||
delayed-stream: 1.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/concat-map@0.0.1:
|
/concat-map@0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -1295,14 +1284,6 @@ packages:
|
||||||
- ts-node
|
- ts-node
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/cross-fetch@4.0.0:
|
|
||||||
resolution: {integrity: sha512-e4a5N8lVvuLgAWgnCrLr2PP0YyDOTHa9H/Rj54dirp61qXnNq46m82bRhNqIA5VccJtWBvPTFRV3TtvHUKPB1g==}
|
|
||||||
dependencies:
|
|
||||||
node-fetch: 2.7.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/cross-spawn@7.0.3:
|
/cross-spawn@7.0.3:
|
||||||
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
@ -1342,11 +1323,6 @@ packages:
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/delayed-stream@1.0.0:
|
|
||||||
resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==}
|
|
||||||
engines: {node: '>=0.4.0'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/detect-newline@3.1.0:
|
/detect-newline@3.1.0:
|
||||||
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
|
resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
|
@ -1646,15 +1622,6 @@ packages:
|
||||||
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
|
resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/form-data@4.0.0:
|
|
||||||
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
|
|
||||||
engines: {node: '>= 6'}
|
|
||||||
dependencies:
|
|
||||||
asynckit: 0.4.0
|
|
||||||
combined-stream: 1.0.8
|
|
||||||
mime-types: 2.1.35
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/fs.realpath@1.0.0:
|
/fs.realpath@1.0.0:
|
||||||
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -2390,13 +2357,8 @@ packages:
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/lemmy-js-client@0.19.4-alpha.8:
|
/lemmy-js-client@0.19.4-alpha.13:
|
||||||
resolution: {integrity: sha512-8vjqUYVOhyUTcmG9FvPLjrWziVwNa2/Zi+kSflTrajJsK0V+5DclJ5dhdVMUQ4DEA70gb0OuNMDlipPG2FoS5A==}
|
resolution: {integrity: sha512-ru1dCqPSfOJdsGq7am5J7P7f+/hpyHGhNbCEV/JAZP2U1lGHul32gLpBkilDnStDNdeq52scjKx+3WskRJFGFA==}
|
||||||
dependencies:
|
|
||||||
cross-fetch: 4.0.0
|
|
||||||
form-data: 4.0.0
|
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/leven@3.1.0:
|
/leven@3.1.0:
|
||||||
|
@ -2485,18 +2447,6 @@ packages:
|
||||||
picomatch: 2.3.1
|
picomatch: 2.3.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/mime-db@1.52.0:
|
|
||||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mime-types@2.1.35:
|
|
||||||
resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
dependencies:
|
|
||||||
mime-db: 1.52.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/mimic-fn@2.1.0:
|
/mimic-fn@2.1.0:
|
||||||
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
@ -2523,18 +2473,6 @@ packages:
|
||||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/node-fetch@2.7.0:
|
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
|
||||||
engines: {node: 4.x || >=6.0.0}
|
|
||||||
peerDependencies:
|
|
||||||
encoding: ^0.1.0
|
|
||||||
peerDependenciesMeta:
|
|
||||||
encoding:
|
|
||||||
optional: true
|
|
||||||
dependencies:
|
|
||||||
whatwg-url: 5.0.0
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/node-int64@0.4.0:
|
/node-int64@0.4.0:
|
||||||
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==}
|
||||||
dev: true
|
dev: true
|
||||||
|
@ -2952,10 +2890,6 @@ packages:
|
||||||
is-number: 7.0.0
|
is-number: 7.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/tr46@0.0.3:
|
|
||||||
resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/ts-api-utils@1.3.0(typescript@5.4.2):
|
/ts-api-utils@1.3.0(typescript@5.4.2):
|
||||||
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
|
resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==}
|
||||||
engines: {node: '>=16'}
|
engines: {node: '>=16'}
|
||||||
|
@ -3067,17 +3001,6 @@ packages:
|
||||||
makeerror: 1.0.12
|
makeerror: 1.0.12
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/webidl-conversions@3.0.1:
|
|
||||||
resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==}
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/whatwg-url@5.0.0:
|
|
||||||
resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==}
|
|
||||||
dependencies:
|
|
||||||
tr46: 0.0.3
|
|
||||||
webidl-conversions: 3.0.1
|
|
||||||
dev: true
|
|
||||||
|
|
||||||
/which@2.0.2:
|
/which@2.0.2:
|
||||||
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==}
|
||||||
engines: {node: '>= 8'}
|
engines: {node: '>= 8'}
|
||||||
|
|
|
@ -5,18 +5,18 @@ import {
|
||||||
setupLogins,
|
setupLogins,
|
||||||
resolveBetaCommunity,
|
resolveBetaCommunity,
|
||||||
followCommunity,
|
followCommunity,
|
||||||
unfollowRemotes,
|
|
||||||
getSite,
|
getSite,
|
||||||
waitUntil,
|
waitUntil,
|
||||||
beta,
|
beta,
|
||||||
betaUrl,
|
betaUrl,
|
||||||
registerUser,
|
registerUser,
|
||||||
|
unfollows,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
|
|
||||||
beforeAll(setupLogins);
|
beforeAll(setupLogins);
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
unfollowRemotes(alpha);
|
unfollows();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Follow local community", async () => {
|
test("Follow local community", async () => {
|
||||||
|
|
|
@ -14,28 +14,33 @@ import {
|
||||||
betaUrl,
|
betaUrl,
|
||||||
createCommunity,
|
createCommunity,
|
||||||
createPost,
|
createPost,
|
||||||
|
deleteAllImages,
|
||||||
delta,
|
delta,
|
||||||
epsilon,
|
epsilon,
|
||||||
followCommunity,
|
followCommunity,
|
||||||
gamma,
|
gamma,
|
||||||
getSite,
|
getSite,
|
||||||
|
imageFetchLimit,
|
||||||
registerUser,
|
registerUser,
|
||||||
resolveBetaCommunity,
|
resolveBetaCommunity,
|
||||||
resolveCommunity,
|
resolveCommunity,
|
||||||
resolvePost,
|
resolvePost,
|
||||||
setupLogins,
|
setupLogins,
|
||||||
unfollowRemotes,
|
|
||||||
waitForPost,
|
waitForPost,
|
||||||
|
unfollows,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
const downloadFileSync = require("download-file-sync");
|
const downloadFileSync = require("download-file-sync");
|
||||||
|
|
||||||
beforeAll(setupLogins);
|
beforeAll(setupLogins);
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
unfollowRemotes(alphaImage);
|
unfollows();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Upload image and delete it", async () => {
|
test("Upload image and delete it", async () => {
|
||||||
|
// Before running this test, you need to delete all previous images in the DB
|
||||||
|
await deleteAllImages(alpha);
|
||||||
|
|
||||||
// Upload test image. We use a simple string buffer as pictrs doesnt require an actual image
|
// Upload test image. We use a simple string buffer as pictrs doesnt require an actual image
|
||||||
// in testing mode.
|
// in testing mode.
|
||||||
const upload_form: UploadImage = {
|
const upload_form: UploadImage = {
|
||||||
|
@ -51,6 +56,24 @@ test("Upload image and delete it", async () => {
|
||||||
const content = downloadFileSync(upload.url);
|
const content = downloadFileSync(upload.url);
|
||||||
expect(content.length).toBeGreaterThan(0);
|
expect(content.length).toBeGreaterThan(0);
|
||||||
|
|
||||||
|
// Ensure that it comes back with the list_media endpoint
|
||||||
|
const listMediaRes = await alphaImage.listMedia();
|
||||||
|
expect(listMediaRes.images.length).toBe(1);
|
||||||
|
|
||||||
|
// Ensure that it also comes back with the admin all images
|
||||||
|
const listAllMediaRes = await alphaImage.listAllMedia({
|
||||||
|
limit: imageFetchLimit,
|
||||||
|
});
|
||||||
|
|
||||||
|
// This number comes from all the previous thumbnails fetched in other tests.
|
||||||
|
const previousThumbnails = 1;
|
||||||
|
expect(listAllMediaRes.images.length).toBe(previousThumbnails);
|
||||||
|
|
||||||
|
// The deleteUrl is a combination of the endpoint, delete token, and alias
|
||||||
|
let firstImage = listMediaRes.images[0];
|
||||||
|
let deleteUrl = `${alphaUrl}/pictrs/image/delete/${firstImage.pictrs_delete_token}/${firstImage.pictrs_alias}`;
|
||||||
|
expect(deleteUrl).toBe(upload.delete_url);
|
||||||
|
|
||||||
// delete image
|
// delete image
|
||||||
const delete_form: DeleteImage = {
|
const delete_form: DeleteImage = {
|
||||||
token: upload.files![0].delete_token,
|
token: upload.files![0].delete_token,
|
||||||
|
@ -62,6 +85,16 @@ test("Upload image and delete it", async () => {
|
||||||
// ensure that image is deleted
|
// ensure that image is deleted
|
||||||
const content2 = downloadFileSync(upload.url);
|
const content2 = downloadFileSync(upload.url);
|
||||||
expect(content2).toBe("");
|
expect(content2).toBe("");
|
||||||
|
|
||||||
|
// Ensure that it shows the image is deleted
|
||||||
|
const deletedListMediaRes = await alphaImage.listMedia();
|
||||||
|
expect(deletedListMediaRes.images.length).toBe(0);
|
||||||
|
|
||||||
|
// Ensure that the admin shows its deleted
|
||||||
|
const deletedListAllMediaRes = await alphaImage.listAllMedia({
|
||||||
|
limit: imageFetchLimit,
|
||||||
|
});
|
||||||
|
expect(deletedListAllMediaRes.images.length).toBe(previousThumbnails - 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Purge user, uploaded image removed", async () => {
|
test("Purge user, uploaded image removed", async () => {
|
||||||
|
@ -83,10 +116,10 @@ test("Purge user, uploaded image removed", async () => {
|
||||||
|
|
||||||
// purge user
|
// purge user
|
||||||
let site = await getSite(user);
|
let site = await getSite(user);
|
||||||
const purge_form: PurgePerson = {
|
const purgeForm: PurgePerson = {
|
||||||
person_id: site.my_user!.local_user_view.person.id,
|
person_id: site.my_user!.local_user_view.person.id,
|
||||||
};
|
};
|
||||||
const delete_ = await alphaImage.purgePerson(purge_form);
|
const delete_ = await alphaImage.purgePerson(purgeForm);
|
||||||
expect(delete_.success).toBe(true);
|
expect(delete_.success).toBe(true);
|
||||||
|
|
||||||
// ensure that image is deleted
|
// ensure that image is deleted
|
||||||
|
@ -120,10 +153,11 @@ test("Purge post, linked image removed", async () => {
|
||||||
expect(post.post_view.post.url).toBe(upload.url);
|
expect(post.post_view.post.url).toBe(upload.url);
|
||||||
|
|
||||||
// purge post
|
// purge post
|
||||||
const purge_form: PurgePost = {
|
|
||||||
|
const purgeForm: PurgePost = {
|
||||||
post_id: post.post_view.post.id,
|
post_id: post.post_view.post.id,
|
||||||
};
|
};
|
||||||
const delete_ = await beta.purgePost(purge_form);
|
const delete_ = await beta.purgePost(purgeForm);
|
||||||
expect(delete_.success).toBe(true);
|
expect(delete_.success).toBe(true);
|
||||||
|
|
||||||
// ensure that image is deleted
|
// ensure that image is deleted
|
||||||
|
|
|
@ -8,9 +8,9 @@ import {
|
||||||
editPrivateMessage,
|
editPrivateMessage,
|
||||||
listPrivateMessages,
|
listPrivateMessages,
|
||||||
deletePrivateMessage,
|
deletePrivateMessage,
|
||||||
unfollowRemotes,
|
|
||||||
waitUntil,
|
waitUntil,
|
||||||
reportPrivateMessage,
|
reportPrivateMessage,
|
||||||
|
unfollows,
|
||||||
} from "./shared";
|
} from "./shared";
|
||||||
|
|
||||||
let recipient_id: number;
|
let recipient_id: number;
|
||||||
|
@ -22,7 +22,7 @@ beforeAll(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
afterAll(() => {
|
afterAll(() => {
|
||||||
unfollowRemotes(alpha);
|
unfollows();
|
||||||
});
|
});
|
||||||
|
|
||||||
test("Create a private message", async () => {
|
test("Create a private message", async () => {
|
||||||
|
|
|
@ -5,6 +5,7 @@ import {
|
||||||
BlockInstanceResponse,
|
BlockInstanceResponse,
|
||||||
CommunityId,
|
CommunityId,
|
||||||
CreatePrivateMessageReport,
|
CreatePrivateMessageReport,
|
||||||
|
DeleteImage,
|
||||||
EditCommunity,
|
EditCommunity,
|
||||||
GetReplies,
|
GetReplies,
|
||||||
GetRepliesResponse,
|
GetRepliesResponse,
|
||||||
|
@ -79,6 +80,7 @@ import { GetPersonDetails } from "lemmy-js-client/dist/types/GetPersonDetails";
|
||||||
import { ListingType } from "lemmy-js-client/dist/types/ListingType";
|
import { ListingType } from "lemmy-js-client/dist/types/ListingType";
|
||||||
|
|
||||||
export const fetchFunction = fetch;
|
export const fetchFunction = fetch;
|
||||||
|
export const imageFetchLimit = 50;
|
||||||
|
|
||||||
export let alphaUrl = "http://127.0.0.1:8541";
|
export let alphaUrl = "http://127.0.0.1:8541";
|
||||||
export let betaUrl = "http://127.0.0.1:8551";
|
export let betaUrl = "http://127.0.0.1:8551";
|
||||||
|
@ -865,9 +867,25 @@ export function randomString(length: number): string {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function deleteAllImages(api: LemmyHttp) {
|
||||||
|
const imagesRes = await api.listAllMedia({
|
||||||
|
limit: imageFetchLimit,
|
||||||
|
});
|
||||||
|
imagesRes.images;
|
||||||
|
|
||||||
|
for (const image of imagesRes.images) {
|
||||||
|
const form: DeleteImage = {
|
||||||
|
token: image.pictrs_delete_token,
|
||||||
|
filename: image.pictrs_alias,
|
||||||
|
};
|
||||||
|
await api.deleteImage(form);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export async function unfollows() {
|
export async function unfollows() {
|
||||||
await Promise.all([
|
await Promise.all([
|
||||||
unfollowRemotes(alpha),
|
unfollowRemotes(alpha),
|
||||||
|
unfollowRemotes(beta),
|
||||||
unfollowRemotes(gamma),
|
unfollowRemotes(gamma),
|
||||||
unfollowRemotes(delta),
|
unfollowRemotes(delta),
|
||||||
unfollowRemotes(epsilon),
|
unfollowRemotes(epsilon),
|
||||||
|
|
|
@ -139,3 +139,23 @@ test("Create user with Arabic name", async () => {
|
||||||
let alphaPerson = (await resolvePerson(alpha, apShortname)).person;
|
let alphaPerson = (await resolvePerson(alpha, apShortname)).person;
|
||||||
expect(alphaPerson).toBeDefined();
|
expect(alphaPerson).toBeDefined();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test("Create user with accept-language", async () => {
|
||||||
|
let lemmy_http = new LemmyHttp(alphaUrl, {
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language#syntax
|
||||||
|
headers: { "Accept-Language": "fr-CH, en;q=0.8, de;q=0.7, *;q=0.5" },
|
||||||
|
});
|
||||||
|
let user = await registerUser(lemmy_http, alphaUrl);
|
||||||
|
|
||||||
|
let site = await getSite(user);
|
||||||
|
expect(site.my_user).toBeDefined();
|
||||||
|
expect(site.my_user?.local_user_view.local_user.interface_language).toBe(
|
||||||
|
"fr",
|
||||||
|
);
|
||||||
|
let langs = site.all_languages
|
||||||
|
.filter(a => site.my_user?.discussion_languages.includes(a.id))
|
||||||
|
.map(l => l.code);
|
||||||
|
// should have languages from accept header, as well as "undetermined"
|
||||||
|
// which is automatically enabled by backend
|
||||||
|
expect(langs).toStrictEqual(["und", "de", "en", "fr"]);
|
||||||
|
});
|
||||||
|
|
|
@ -259,9 +259,9 @@ pub async fn local_user_view_from_jwt(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,7 @@ use lemmy_api_common::{
|
||||||
person::GenerateTotpSecretResponse,
|
person::GenerateTotpSecretResponse,
|
||||||
sensitive::Sensitive,
|
sensitive::Sensitive,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::source::local_user::{LocalUser, LocalUserUpdateForm};
|
||||||
source::local_user::{LocalUser, LocalUserUpdateForm},
|
|
||||||
traits::Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
use lemmy_db_views::structs::{LocalUserView, SiteView};
|
||||||
use lemmy_utils::error::{LemmyError, LemmyErrorType};
|
use lemmy_utils::error::{LemmyError, LemmyErrorType};
|
||||||
|
|
||||||
|
|
26
crates/api/src/local_user/list_media.rs
Normal file
26
crates/api/src/local_user/list_media.rs
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
use actix_web::web::{Data, Json, Query};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
person::{ListMedia, ListMediaResponse},
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::images::LocalImage;
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn list_media(
|
||||||
|
data: Query<ListMedia>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
) -> Result<Json<ListMediaResponse>, LemmyError> {
|
||||||
|
let page = data.page;
|
||||||
|
let limit = data.limit;
|
||||||
|
let images = LocalImage::get_all_paged_by_local_user_id(
|
||||||
|
&mut context.pool(),
|
||||||
|
local_user_view.local_user.id,
|
||||||
|
page,
|
||||||
|
limit,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
Ok(Json(ListMediaResponse { images }))
|
||||||
|
}
|
|
@ -10,6 +10,7 @@ pub mod generate_totp_secret;
|
||||||
pub mod get_captcha;
|
pub mod get_captcha;
|
||||||
pub mod list_banned;
|
pub mod list_banned;
|
||||||
pub mod list_logins;
|
pub mod list_logins;
|
||||||
|
pub mod list_media;
|
||||||
pub mod login;
|
pub mod login;
|
||||||
pub mod logout;
|
pub mod logout;
|
||||||
pub mod notifications;
|
pub mod notifications;
|
||||||
|
|
|
@ -4,10 +4,7 @@ use lemmy_api_common::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
person::{UpdateTotp, UpdateTotpResponse},
|
person::{UpdateTotp, UpdateTotpResponse},
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::source::local_user::{LocalUser, LocalUserUpdateForm};
|
||||||
source::local_user::{LocalUser, LocalUserUpdateForm},
|
|
||||||
traits::Crud,
|
|
||||||
};
|
|
||||||
use lemmy_db_views::structs::LocalUserView;
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
use lemmy_utils::error::LemmyError;
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
|
24
crates/api/src/site/list_all_media.rs
Normal file
24
crates/api/src/site/list_all_media.rs
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
use actix_web::web::{Data, Json, Query};
|
||||||
|
use lemmy_api_common::{
|
||||||
|
context::LemmyContext,
|
||||||
|
person::{ListMedia, ListMediaResponse},
|
||||||
|
utils::is_admin,
|
||||||
|
};
|
||||||
|
use lemmy_db_schema::source::images::LocalImage;
|
||||||
|
use lemmy_db_views::structs::LocalUserView;
|
||||||
|
use lemmy_utils::error::LemmyError;
|
||||||
|
|
||||||
|
#[tracing::instrument(skip(context))]
|
||||||
|
pub async fn list_all_media(
|
||||||
|
data: Query<ListMedia>,
|
||||||
|
context: Data<LemmyContext>,
|
||||||
|
local_user_view: LocalUserView,
|
||||||
|
) -> Result<Json<ListMediaResponse>, LemmyError> {
|
||||||
|
// Only let admins view all media
|
||||||
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
|
let page = data.page;
|
||||||
|
let limit = data.limit;
|
||||||
|
let images = LocalImage::get_all(&mut context.pool(), page, limit).await?;
|
||||||
|
Ok(Json(ListMediaResponse { images }))
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
pub mod block;
|
pub mod block;
|
||||||
pub mod federated_instances;
|
pub mod federated_instances;
|
||||||
pub mod leave_admin;
|
pub mod leave_admin;
|
||||||
|
pub mod list_all_media;
|
||||||
pub mod mod_log;
|
pub mod mod_log;
|
||||||
pub mod purge;
|
pub mod purge;
|
||||||
pub mod registration_applications;
|
pub mod registration_applications;
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub async fn purge_person(
|
||||||
// Read the local user to get their images, and delete them
|
// Read the local user to get their images, and delete them
|
||||||
if let Ok(local_user) = LocalUserView::read_person(&mut context.pool(), data.person_id).await {
|
if let Ok(local_user) = LocalUserView::read_person(&mut context.pool(), data.person_id).await {
|
||||||
let pictrs_uploads =
|
let pictrs_uploads =
|
||||||
LocalImage::get_all_by_local_user_id(&mut context.pool(), &local_user.local_user.id).await?;
|
LocalImage::get_all_by_local_user_id(&mut context.pool(), local_user.local_user.id).await?;
|
||||||
|
|
||||||
for upload in pictrs_uploads {
|
for upload in pictrs_uploads {
|
||||||
delete_image_from_pictrs(&upload.pictrs_alias, &upload.pictrs_delete_token, &context)
|
delete_image_from_pictrs(&upload.pictrs_alias, &upload.pictrs_delete_token, &context)
|
||||||
|
|
|
@ -42,8 +42,8 @@ pub async fn get_sitemap(context: Data<LemmyContext>) -> LemmyResult<HttpRespons
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
|
|
||||||
use crate::sitemap::generate_urlset;
|
use crate::sitemap::generate_urlset;
|
||||||
use chrono::{DateTime, NaiveDate, Utc};
|
use chrono::{DateTime, NaiveDate, Utc};
|
||||||
|
|
|
@ -72,9 +72,9 @@ impl Claims {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{claims::Claims, context::LemmyContext};
|
use crate::{claims::Claims, context::LemmyContext};
|
||||||
use actix_web::test::TestRequest;
|
use actix_web::test::TestRequest;
|
||||||
|
@ -124,7 +124,9 @@ mod tests {
|
||||||
.password_encrypted("123456".to_string())
|
.password_encrypted("123456".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
|
let inserted_local_user = LocalUser::create(pool, &local_user_form, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let req = TestRequest::default().to_http_request();
|
let req = TestRequest::default().to_http_request();
|
||||||
let jwt = Claims::generate(inserted_local_user.id, req, &context)
|
let jwt = Claims::generate(inserted_local_user.id, req, &context)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::sensitive::Sensitive;
|
use crate::sensitive::Sensitive;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
newtypes::{CommentReplyId, CommunityId, LanguageId, PersonId, PersonMentionId},
|
||||||
source::site::Site,
|
source::{images::LocalImage, site::Site},
|
||||||
CommentSortType,
|
CommentSortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
PostListingMode,
|
PostListingMode,
|
||||||
|
@ -422,3 +422,20 @@ pub struct UpdateTotp {
|
||||||
pub struct UpdateTotpResponse {
|
pub struct UpdateTotpResponse {
|
||||||
pub enabled: bool,
|
pub enabled: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[skip_serializing_none]
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default, PartialEq, Eq, Hash)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
/// Get your user's image / media uploads.
|
||||||
|
pub struct ListMedia {
|
||||||
|
pub page: Option<i64>,
|
||||||
|
pub limit: Option<i64>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||||
|
#[cfg_attr(feature = "full", derive(TS))]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
|
pub struct ListMediaResponse {
|
||||||
|
pub images: Vec<LocalImage>,
|
||||||
|
}
|
||||||
|
|
|
@ -365,9 +365,9 @@ async fn is_image_content_type(client: &ClientWithMiddleware, url: &Url) -> Resu
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
context::LemmyContext,
|
context::LemmyContext,
|
||||||
|
|
|
@ -1019,9 +1019,9 @@ pub async fn proxy_image_link_opt_apub(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -164,10 +164,15 @@ pub async fn create_comment(
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
// If its a reply, mark the parent as read
|
// If we're responding to a comment where we're the recipient,
|
||||||
|
// (ie we're the grandparent, or the recipient of the parent comment_reply),
|
||||||
|
// then mark the parent as read.
|
||||||
|
// Then we don't have to do it manually after we respond to a comment.
|
||||||
if let Some(parent) = parent_opt {
|
if let Some(parent) = parent_opt {
|
||||||
|
let person_id = local_user_view.person.id;
|
||||||
let parent_id = parent.id;
|
let parent_id = parent.id;
|
||||||
let comment_reply = CommentReply::read_by_comment(&mut context.pool(), parent_id).await;
|
let comment_reply =
|
||||||
|
CommentReply::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await;
|
||||||
if let Ok(reply) = comment_reply {
|
if let Ok(reply) = comment_reply {
|
||||||
CommentReply::update(
|
CommentReply::update(
|
||||||
&mut context.pool(),
|
&mut context.pool(),
|
||||||
|
@ -179,7 +184,6 @@ pub async fn create_comment(
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the parent has PersonMentions mark them as read too
|
// If the parent has PersonMentions mark them as read too
|
||||||
let person_id = local_user_view.person.id;
|
|
||||||
let person_mention =
|
let person_mention =
|
||||||
PersonMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await;
|
PersonMention::read_by_comment_and_person(&mut context.pool(), parent_id, person_id).await;
|
||||||
if let Ok(mention) = person_mention {
|
if let Ok(mention) = person_mention {
|
||||||
|
|
|
@ -189,9 +189,9 @@ fn validate_create_payload(local_site: &LocalSite, create_site: &CreateSite) ->
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::site::create::validate_create_payload;
|
use crate::site::create::validate_create_payload;
|
||||||
use lemmy_api_common::site::CreateSite;
|
use lemmy_api_common::site::CreateSite;
|
||||||
|
|
|
@ -41,9 +41,9 @@ pub fn application_question_check(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::site::{application_question_check, site_default_post_listing_type_check};
|
use crate::site::{application_question_check, site_default_post_listing_type_check};
|
||||||
use lemmy_db_schema::{ListingType, RegistrationMode};
|
use lemmy_db_schema::{ListingType, RegistrationMode};
|
||||||
|
|
|
@ -231,9 +231,9 @@ fn validate_update_payload(local_site: &LocalSite, edit_site: &EditSite) -> Lemm
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::site::update::validate_update_payload;
|
use crate::site::update::validate_update_payload;
|
||||||
use lemmy_api_common::site::EditSite;
|
use lemmy_api_common::site::EditSite;
|
||||||
|
|
|
@ -20,6 +20,7 @@ use lemmy_db_schema::{
|
||||||
aggregates::structs::PersonAggregates,
|
aggregates::structs::PersonAggregates,
|
||||||
source::{
|
source::{
|
||||||
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
|
captcha_answer::{CaptchaAnswer, CheckCaptchaAnswer},
|
||||||
|
language::Language,
|
||||||
local_user::{LocalUser, LocalUserInsertForm},
|
local_user::{LocalUser, LocalUserInsertForm},
|
||||||
local_user_vote_display_mode::LocalUserVoteDisplayMode,
|
local_user_vote_display_mode::LocalUserVoteDisplayMode,
|
||||||
person::{Person, PersonInsertForm},
|
person::{Person, PersonInsertForm},
|
||||||
|
@ -36,6 +37,7 @@ use lemmy_utils::{
|
||||||
validation::is_valid_actor_name,
|
validation::is_valid_actor_name,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
use std::collections::HashSet;
|
||||||
|
|
||||||
#[tracing::instrument(skip(context))]
|
#[tracing::instrument(skip(context))]
|
||||||
pub async fn register(
|
pub async fn register(
|
||||||
|
@ -128,12 +130,15 @@ pub async fn register(
|
||||||
let accepted_application = Some(!require_registration_application);
|
let accepted_application = Some(!require_registration_application);
|
||||||
|
|
||||||
// Get the user's preferred language using the Accept-Language header
|
// Get the user's preferred language using the Accept-Language header
|
||||||
let language_tag = req.headers().get("Accept-Language").and_then(|hdr| {
|
let language_tags: Vec<String> = req
|
||||||
accept_language::parse(hdr.to_str().unwrap_or_default())
|
.headers()
|
||||||
.first()
|
.get("Accept-Language")
|
||||||
// Remove the optional region code
|
.map(|hdr| accept_language::parse(hdr.to_str().unwrap_or_default()))
|
||||||
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string())
|
.iter()
|
||||||
});
|
.flatten()
|
||||||
|
// Remove the optional region code
|
||||||
|
.map(|lang_str| lang_str.split('-').next().unwrap_or_default().to_string())
|
||||||
|
.collect();
|
||||||
|
|
||||||
// Create the local user
|
// Create the local user
|
||||||
let local_user_form = LocalUserInsertForm::builder()
|
let local_user_form = LocalUserInsertForm::builder()
|
||||||
|
@ -144,12 +149,23 @@ pub async fn register(
|
||||||
.accepted_application(accepted_application)
|
.accepted_application(accepted_application)
|
||||||
.default_listing_type(Some(local_site.default_post_listing_type))
|
.default_listing_type(Some(local_site.default_post_listing_type))
|
||||||
.post_listing_mode(Some(local_site.default_post_listing_mode))
|
.post_listing_mode(Some(local_site.default_post_listing_mode))
|
||||||
.interface_language(language_tag)
|
.interface_language(language_tags.first().cloned())
|
||||||
// If its the initial site setup, they are an admin
|
// If its the initial site setup, they are an admin
|
||||||
.admin(Some(!local_site.site_setup))
|
.admin(Some(!local_site.site_setup))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_local_user = LocalUser::create(&mut context.pool(), &local_user_form).await?;
|
let all_languages = Language::read_all(&mut context.pool()).await?;
|
||||||
|
// use hashset to avoid duplicates
|
||||||
|
let mut language_ids = HashSet::new();
|
||||||
|
for l in language_tags {
|
||||||
|
if let Some(found) = all_languages.iter().find(|all| all.code == l) {
|
||||||
|
language_ids.insert(found.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let language_ids = language_ids.into_iter().collect();
|
||||||
|
|
||||||
|
let inserted_local_user =
|
||||||
|
LocalUser::create(&mut context.pool(), &local_user_form, language_ids).await?;
|
||||||
|
|
||||||
if local_site.site_setup && require_registration_application {
|
if local_site.site_setup && require_registration_application {
|
||||||
// Create the registration application
|
// Create the registration application
|
||||||
|
|
|
@ -72,6 +72,7 @@ impl BlockUser {
|
||||||
)?,
|
)?,
|
||||||
audience,
|
audience,
|
||||||
expires,
|
expires,
|
||||||
|
end_time: expires,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -149,7 +150,7 @@ impl ActivityHandler for BlockUser {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
|
async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
|
||||||
insert_received_activity(&self.id, context).await?;
|
insert_received_activity(&self.id, context).await?;
|
||||||
let expires = self.expires.map(Into::into);
|
let expires = self.expires.or(self.end_time).map(Into::into);
|
||||||
let mod_person = self.actor.dereference(context).await?;
|
let mod_person = self.actor.dereference(context).await?;
|
||||||
let blocked_person = self.object.dereference(context).await?;
|
let blocked_person = self.object.dereference(context).await?;
|
||||||
let target = self.target.dereference(context).await?;
|
let target = self.target.dereference(context).await?;
|
||||||
|
|
|
@ -98,7 +98,7 @@ impl ActivityHandler for UndoBlockUser {
|
||||||
#[tracing::instrument(skip_all)]
|
#[tracing::instrument(skip_all)]
|
||||||
async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
|
async fn receive(self, context: &Data<LemmyContext>) -> Result<(), LemmyError> {
|
||||||
insert_received_activity(&self.id, context).await?;
|
insert_received_activity(&self.id, context).await?;
|
||||||
let expires = self.object.expires.map(Into::into);
|
let expires = self.object.expires.or(self.object.end_time).map(Into::into);
|
||||||
let mod_person = self.actor.dereference(context).await?;
|
let mod_person = self.actor.dereference(context).await?;
|
||||||
let blocked_person = self.object.object.dereference(context).await?;
|
let blocked_person = self.object.object.dereference(context).await?;
|
||||||
match self.object.target.dereference(context).await? {
|
match self.object.target.dereference(context).await? {
|
||||||
|
|
|
@ -123,8 +123,8 @@ impl InCommunity for AnnouncableActivities {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
activity_lists::{GroupInboxActivities, PersonInboxActivities, SharedInboxActivities},
|
activity_lists::{GroupInboxActivities, PersonInboxActivities, SharedInboxActivities},
|
||||||
|
|
|
@ -319,8 +319,8 @@ pub async fn import_settings(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::api::user_settings_backup::{export_settings, import_settings};
|
use crate::api::user_settings_backup::{export_settings, import_settings};
|
||||||
use activitypub_federation::config::Data;
|
use activitypub_federation::config::Data;
|
||||||
|
@ -361,7 +361,7 @@ mod tests {
|
||||||
.person_id(person.id)
|
.person_id(person.id)
|
||||||
.password_encrypted("pass".to_string())
|
.password_encrypted("pass".to_string())
|
||||||
.build();
|
.build();
|
||||||
let local_user = LocalUser::create(&mut context.pool(), &user_form).await?;
|
let local_user = LocalUser::create(&mut context.pool(), &user_form, vec![]).await?;
|
||||||
|
|
||||||
Ok(LocalUserView::read(&mut context.pool(), local_user.id).await?)
|
Ok(LocalUserView::read(&mut context.pool(), local_user.id).await?)
|
||||||
}
|
}
|
||||||
|
|
|
@ -101,8 +101,8 @@ impl Collection for ApubCommunityModerators {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -115,9 +115,9 @@ pub(crate) async fn get_apub_community_featured(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
pub(crate) mod tests {
|
pub(crate) mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::protocol::objects::{group::Group, tombstone::Tombstone};
|
use crate::protocol::objects::{group::Group, tombstone::Tombstone};
|
||||||
|
|
|
@ -38,7 +38,9 @@ pub struct BlockUser {
|
||||||
pub(crate) remove_data: Option<bool>,
|
pub(crate) remove_data: Option<bool>,
|
||||||
/// block reason, written to mod log
|
/// block reason, written to mod log
|
||||||
pub(crate) summary: Option<String>,
|
pub(crate) summary: Option<String>,
|
||||||
|
/// TODO: deprecated
|
||||||
pub(crate) expires: Option<DateTime<Utc>>,
|
pub(crate) expires: Option<DateTime<Utc>>,
|
||||||
|
pub(crate) end_time: Option<DateTime<Utc>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait]
|
#[async_trait::async_trait]
|
||||||
|
|
|
@ -33,9 +33,9 @@ impl CommentAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::comment_aggregates::CommentAggregates,
|
aggregates::comment_aggregates::CommentAggregates,
|
||||||
|
|
|
@ -31,9 +31,9 @@ impl CommunityAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::community_aggregates::CommunityAggregates,
|
aggregates::community_aggregates::CommunityAggregates,
|
||||||
|
|
|
@ -18,9 +18,9 @@ impl PersonAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::person_aggregates::PersonAggregates,
|
aggregates::person_aggregates::PersonAggregates,
|
||||||
|
|
|
@ -52,9 +52,9 @@ impl PostAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::post_aggregates::PostAggregates,
|
aggregates::post_aggregates::PostAggregates,
|
||||||
|
|
|
@ -14,9 +14,9 @@ impl SiteAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::site_aggregates::SiteAggregates,
|
aggregates::site_aggregates::SiteAggregates,
|
||||||
|
|
|
@ -61,9 +61,9 @@ impl ReceivedActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{source::activity::ActorType, utils::build_db_pool_for_tests};
|
use crate::{source::activity::ActorType, utils::build_db_pool_for_tests};
|
||||||
|
|
|
@ -385,9 +385,9 @@ async fn convert_read_languages(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -523,10 +523,6 @@ mod tests {
|
||||||
let pool = &mut pool.into();
|
let pool = &mut pool.into();
|
||||||
|
|
||||||
let (site, instance) = create_test_site(pool).await;
|
let (site, instance) = create_test_site(pool).await;
|
||||||
let mut test_langs = test_langs1(pool).await;
|
|
||||||
SiteLanguage::update(pool, test_langs.clone(), &site)
|
|
||||||
.await
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let person_form = PersonInsertForm::builder()
|
let person_form = PersonInsertForm::builder()
|
||||||
.name("my test person".to_string())
|
.name("my test person".to_string())
|
||||||
|
@ -539,14 +535,13 @@ mod tests {
|
||||||
.password_encrypted("my_pw".to_string())
|
.password_encrypted("my_pw".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
|
let local_user = LocalUser::create(pool, &local_user_form, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let local_user_langs1 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
|
let local_user_langs1 = LocalUserLanguage::read(pool, local_user.id).await.unwrap();
|
||||||
|
|
||||||
// new user should be initialized with site languages and undetermined
|
// new user should be initialized with all languages
|
||||||
//test_langs.push(UNDETERMINED_ID);
|
assert_eq!(0, local_user_langs1.len());
|
||||||
//test_langs.sort();
|
|
||||||
test_langs.insert(0, UNDETERMINED_ID);
|
|
||||||
assert_eq!(test_langs, local_user_langs1);
|
|
||||||
|
|
||||||
// update user languages
|
// update user languages
|
||||||
let test_langs2 = test_langs2(pool).await;
|
let test_langs2 = test_langs2(pool).await;
|
||||||
|
@ -655,7 +650,9 @@ mod tests {
|
||||||
.person_id(person.id)
|
.person_id(person.id)
|
||||||
.password_encrypted("my_pw".to_string())
|
.password_encrypted("my_pw".to_string())
|
||||||
.build();
|
.build();
|
||||||
let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
|
let local_user = LocalUser::create(pool, &local_user_form, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
LocalUserLanguage::update(pool, test_langs2, local_user.id)
|
LocalUserLanguage::update(pool, test_langs2, local_user.id)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -48,9 +48,9 @@ impl CaptchaAnswer {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::captcha_answer::{CaptchaAnswer, CaptchaAnswerForm, CheckCaptchaAnswer},
|
source::captcha_answer::{CaptchaAnswer, CaptchaAnswerForm, CheckCaptchaAnswer},
|
||||||
|
|
|
@ -241,9 +241,9 @@ impl Saveable for CommentSaved {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::LanguageId,
|
newtypes::LanguageId,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{CommentId, CommentReplyId, PersonId},
|
newtypes::{CommentId, CommentReplyId, PersonId},
|
||||||
schema::comment_reply::dsl::{comment_id, comment_reply, read, recipient_id},
|
schema::comment_reply,
|
||||||
source::comment_reply::{CommentReply, CommentReplyInsertForm, CommentReplyUpdateForm},
|
source::comment_reply::{CommentReply, CommentReplyInsertForm, CommentReplyUpdateForm},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
|
@ -22,9 +22,9 @@ impl Crud for CommentReply {
|
||||||
|
|
||||||
// since the return here isnt utilized, we dont need to do an update
|
// since the return here isnt utilized, we dont need to do an update
|
||||||
// but get_result doesnt return the existing row here
|
// but get_result doesnt return the existing row here
|
||||||
insert_into(comment_reply)
|
insert_into(comment_reply::table)
|
||||||
.values(comment_reply_form)
|
.values(comment_reply_form)
|
||||||
.on_conflict((recipient_id, comment_id))
|
.on_conflict((comment_reply::recipient_id, comment_reply::comment_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(comment_reply_form)
|
.set(comment_reply_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -37,7 +37,7 @@ impl Crud for CommentReply {
|
||||||
comment_reply_form: &Self::UpdateForm,
|
comment_reply_form: &Self::UpdateForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(comment_reply.find(comment_reply_id))
|
diesel::update(comment_reply::table.find(comment_reply_id))
|
||||||
.set(comment_reply_form)
|
.set(comment_reply_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
|
@ -51,11 +51,11 @@ impl CommentReply {
|
||||||
) -> Result<Vec<CommentReply>, Error> {
|
) -> Result<Vec<CommentReply>, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(
|
diesel::update(
|
||||||
comment_reply
|
comment_reply::table
|
||||||
.filter(recipient_id.eq(for_recipient_id))
|
.filter(comment_reply::recipient_id.eq(for_recipient_id))
|
||||||
.filter(read.eq(false)),
|
.filter(comment_reply::read.eq(false)),
|
||||||
)
|
)
|
||||||
.set(read.eq(true))
|
.set(comment_reply::read.eq(true))
|
||||||
.get_results::<Self>(conn)
|
.get_results::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -65,17 +65,30 @@ impl CommentReply {
|
||||||
for_comment_id: CommentId,
|
for_comment_id: CommentId,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
comment_reply
|
comment_reply::table
|
||||||
.filter(comment_id.eq(for_comment_id))
|
.filter(comment_reply::comment_id.eq(for_comment_id))
|
||||||
|
.first::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn read_by_comment_and_person(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
for_comment_id: CommentId,
|
||||||
|
for_recipient_id: PersonId,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
comment_reply::table
|
||||||
|
.filter(comment_reply::comment_id.eq(for_comment_id))
|
||||||
|
.filter(comment_reply::recipient_id.eq(for_recipient_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -381,9 +381,9 @@ impl ApubActor for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -48,9 +48,9 @@ impl FederationAllowList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{federation_allowlist::FederationAllowList, instance::Instance},
|
source::{federation_allowlist::FederationAllowList, instance::Instance},
|
||||||
|
|
|
@ -1,11 +1,8 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{DbUrl, LocalUserId},
|
newtypes::{DbUrl, LocalUserId},
|
||||||
schema::{
|
schema::{local_image, remote_image},
|
||||||
local_image::dsl::{local_image, local_user_id, pictrs_alias},
|
|
||||||
remote_image::dsl::{link, remote_image},
|
|
||||||
},
|
|
||||||
source::images::{LocalImage, LocalImageForm, RemoteImage, RemoteImageForm},
|
source::images::{LocalImage, LocalImageForm, RemoteImage, RemoteImageForm},
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
};
|
};
|
||||||
use diesel::{
|
use diesel::{
|
||||||
dsl::exists,
|
dsl::exists,
|
||||||
|
@ -15,7 +12,6 @@ use diesel::{
|
||||||
ExpressionMethods,
|
ExpressionMethods,
|
||||||
NotFound,
|
NotFound,
|
||||||
QueryDsl,
|
QueryDsl,
|
||||||
Table,
|
|
||||||
};
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -23,27 +19,64 @@ use url::Url;
|
||||||
impl LocalImage {
|
impl LocalImage {
|
||||||
pub async fn create(pool: &mut DbPool<'_>, form: &LocalImageForm) -> Result<Self, Error> {
|
pub async fn create(pool: &mut DbPool<'_>, form: &LocalImageForm) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
insert_into(local_image)
|
insert_into(local_image::table)
|
||||||
.values(form)
|
.values(form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_all_paged_by_local_user_id(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
user_id: LocalUserId,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, Some(user_id), page, limit, false).await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_all_by_local_user_id(
|
pub async fn get_all_by_local_user_id(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
user_id: &LocalUserId,
|
user_id: LocalUserId,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, Some(user_id), None, None, true).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn get_all(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
|
Self::get_all_helper(pool, None, page, limit, false).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn get_all_helper(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
user_id: Option<LocalUserId>,
|
||||||
|
page: Option<i64>,
|
||||||
|
limit: Option<i64>,
|
||||||
|
ignore_page_limits: bool,
|
||||||
) -> Result<Vec<Self>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
local_image
|
let mut query = local_image::table
|
||||||
.filter(local_user_id.eq(user_id))
|
.select(local_image::all_columns)
|
||||||
.select(local_image::all_columns())
|
.order_by(local_image::published.desc())
|
||||||
.load::<LocalImage>(conn)
|
.into_boxed();
|
||||||
.await
|
|
||||||
|
if let Some(user_id) = user_id {
|
||||||
|
query = query.filter(local_image::local_user_id.eq(user_id))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !ignore_page_limits {
|
||||||
|
let (limit, offset) = limit_and_offset(page, limit)?;
|
||||||
|
query = query.limit(limit).offset(offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
query.load::<LocalImage>(conn).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<usize, Error> {
|
pub async fn delete_by_alias(pool: &mut DbPool<'_>, alias: &str) -> Result<usize, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::delete(local_image.filter(pictrs_alias.eq(alias)))
|
diesel::delete(local_image::table.filter(local_image::pictrs_alias.eq(alias)))
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -56,7 +89,7 @@ impl RemoteImage {
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|url| RemoteImageForm { link: url.into() })
|
.map(|url| RemoteImageForm { link: url.into() })
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
insert_into(remote_image)
|
insert_into(remote_image::table)
|
||||||
.values(forms)
|
.values(forms)
|
||||||
.on_conflict_do_nothing()
|
.on_conflict_do_nothing()
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
|
@ -66,9 +99,11 @@ impl RemoteImage {
|
||||||
pub async fn validate(pool: &mut DbPool<'_>, link_: DbUrl) -> Result<(), Error> {
|
pub async fn validate(pool: &mut DbPool<'_>, link_: DbUrl) -> Result<(), Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
|
||||||
let exists = select(exists(remote_image.filter((link).eq(link_))))
|
let exists = select(exists(
|
||||||
.get_result::<bool>(conn)
|
remote_image::table.filter(remote_image::link.eq(link_)),
|
||||||
.await?;
|
))
|
||||||
|
.get_result::<bool>(conn)
|
||||||
|
.await?;
|
||||||
if exists {
|
if exists {
|
||||||
Ok(())
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -41,9 +41,9 @@ impl Language {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{source::language::Language, utils::build_db_pool_for_tests};
|
use crate::{source::language::Language, utils::build_db_pool_for_tests};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{DbUrl, LocalUserId, PersonId},
|
newtypes::{DbUrl, LanguageId, LocalUserId, PersonId},
|
||||||
schema::{local_user, person, registration_application},
|
schema::{local_user, person, registration_application},
|
||||||
source::{
|
source::{
|
||||||
actor_language::{LocalUserLanguage, SiteLanguage},
|
actor_language::LocalUserLanguage,
|
||||||
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
local_user::{LocalUser, LocalUserInsertForm, LocalUserUpdateForm},
|
||||||
local_user_vote_display_mode::{LocalUserVoteDisplayMode, LocalUserVoteDisplayModeInsertForm},
|
local_user_vote_display_mode::{LocalUserVoteDisplayMode, LocalUserVoteDisplayModeInsertForm},
|
||||||
},
|
},
|
||||||
traits::Crud,
|
|
||||||
utils::{
|
utils::{
|
||||||
functions::{coalesce, lower},
|
functions::{coalesce, lower},
|
||||||
get_conn,
|
get_conn,
|
||||||
|
@ -25,6 +24,52 @@ use diesel::{
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
|
|
||||||
impl LocalUser {
|
impl LocalUser {
|
||||||
|
pub async fn create(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
form: &LocalUserInsertForm,
|
||||||
|
languages: Vec<LanguageId>,
|
||||||
|
) -> Result<LocalUser, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
let mut form_with_encrypted_password = form.clone();
|
||||||
|
let password_hash =
|
||||||
|
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
|
||||||
|
form_with_encrypted_password.password_encrypted = password_hash;
|
||||||
|
|
||||||
|
let local_user_ = insert_into(local_user::table)
|
||||||
|
.values(form_with_encrypted_password)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
LocalUserLanguage::update(pool, languages, local_user_.id).await?;
|
||||||
|
|
||||||
|
// Create their vote_display_modes
|
||||||
|
let vote_display_mode_form = LocalUserVoteDisplayModeInsertForm::builder()
|
||||||
|
.local_user_id(local_user_.id)
|
||||||
|
.build();
|
||||||
|
LocalUserVoteDisplayMode::create(pool, &vote_display_mode_form).await?;
|
||||||
|
|
||||||
|
Ok(local_user_)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn update(
|
||||||
|
pool: &mut DbPool<'_>,
|
||||||
|
local_user_id: LocalUserId,
|
||||||
|
form: &LocalUserUpdateForm,
|
||||||
|
) -> Result<LocalUser, Error> {
|
||||||
|
let conn = &mut get_conn(pool).await?;
|
||||||
|
diesel::update(local_user::table.find(local_user_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn delete(pool: &mut DbPool<'_>, id: LocalUserId) -> Result<usize, Error> {
|
||||||
|
let conn = &mut *get_conn(pool).await?;
|
||||||
|
diesel::delete(local_user::table.find(id))
|
||||||
|
.execute(conn)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn update_password(
|
pub async fn update_password(
|
||||||
pool: &mut DbPool<'_>,
|
pool: &mut DbPool<'_>,
|
||||||
local_user_id: LocalUserId,
|
local_user_id: LocalUserId,
|
||||||
|
@ -183,52 +228,3 @@ pub struct UserBackupLists {
|
||||||
pub blocked_users: Vec<DbUrl>,
|
pub blocked_users: Vec<DbUrl>,
|
||||||
pub blocked_instances: Vec<String>,
|
pub blocked_instances: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
|
||||||
impl Crud for LocalUser {
|
|
||||||
type InsertForm = LocalUserInsertForm;
|
|
||||||
type UpdateForm = LocalUserUpdateForm;
|
|
||||||
type IdType = LocalUserId;
|
|
||||||
|
|
||||||
async fn create(pool: &mut DbPool<'_>, form: &Self::InsertForm) -> Result<Self, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
let mut form_with_encrypted_password = form.clone();
|
|
||||||
let password_hash =
|
|
||||||
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
|
|
||||||
form_with_encrypted_password.password_encrypted = password_hash;
|
|
||||||
|
|
||||||
let local_user_ = insert_into(local_user::table)
|
|
||||||
.values(form_with_encrypted_password)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
let site_languages = SiteLanguage::read_local_raw(pool).await;
|
|
||||||
if let Ok(langs) = site_languages {
|
|
||||||
// if site exists, init user with site languages
|
|
||||||
LocalUserLanguage::update(pool, langs, local_user_.id).await?;
|
|
||||||
} else {
|
|
||||||
// otherwise, init with all languages (this only happens during tests and
|
|
||||||
// for first admin user, which is created before site)
|
|
||||||
LocalUserLanguage::update(pool, vec![], local_user_.id).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create their vote_display_modes
|
|
||||||
let vote_display_mode_form = LocalUserVoteDisplayModeInsertForm::builder()
|
|
||||||
.local_user_id(local_user_.id)
|
|
||||||
.build();
|
|
||||||
LocalUserVoteDisplayMode::create(pool, &vote_display_mode_form).await?;
|
|
||||||
|
|
||||||
Ok(local_user_)
|
|
||||||
}
|
|
||||||
async fn update(
|
|
||||||
pool: &mut DbPool<'_>,
|
|
||||||
local_user_id: LocalUserId,
|
|
||||||
form: &Self::UpdateForm,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
let conn = &mut get_conn(pool).await?;
|
|
||||||
diesel::update(local_user::table.find(local_user_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -465,9 +465,9 @@ impl Crud for AdminPurgeComment {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -81,9 +81,9 @@ impl PasswordResetRequest {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
@ -121,7 +121,9 @@ mod tests {
|
||||||
.password_encrypted("pass".to_string())
|
.password_encrypted("pass".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_local_user = LocalUser::create(pool, &new_local_user).await.unwrap();
|
let inserted_local_user = LocalUser::create(pool, &new_local_user, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let token = "nope";
|
let token = "nope";
|
||||||
|
|
||||||
|
|
|
@ -212,9 +212,9 @@ impl PersonFollower {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
newtypes::{CommentId, PersonId, PersonMentionId},
|
newtypes::{CommentId, PersonId, PersonMentionId},
|
||||||
schema::person_mention::dsl::{comment_id, person_mention, read, recipient_id},
|
schema::person_mention,
|
||||||
source::person_mention::{PersonMention, PersonMentionInsertForm, PersonMentionUpdateForm},
|
source::person_mention::{PersonMention, PersonMentionInsertForm, PersonMentionUpdateForm},
|
||||||
traits::Crud,
|
traits::Crud,
|
||||||
utils::{get_conn, DbPool},
|
utils::{get_conn, DbPool},
|
||||||
|
@ -21,9 +21,9 @@ impl Crud for PersonMention {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
// since the return here isnt utilized, we dont need to do an update
|
// since the return here isnt utilized, we dont need to do an update
|
||||||
// but get_result doesnt return the existing row here
|
// but get_result doesnt return the existing row here
|
||||||
insert_into(person_mention)
|
insert_into(person_mention::table)
|
||||||
.values(person_mention_form)
|
.values(person_mention_form)
|
||||||
.on_conflict((recipient_id, comment_id))
|
.on_conflict((person_mention::recipient_id, person_mention::comment_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(person_mention_form)
|
.set(person_mention_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -36,7 +36,7 @@ impl Crud for PersonMention {
|
||||||
person_mention_form: &Self::UpdateForm,
|
person_mention_form: &Self::UpdateForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(person_mention.find(person_mention_id))
|
diesel::update(person_mention::table.find(person_mention_id))
|
||||||
.set(person_mention_form)
|
.set(person_mention_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
|
@ -50,11 +50,11 @@ impl PersonMention {
|
||||||
) -> Result<Vec<PersonMention>, Error> {
|
) -> Result<Vec<PersonMention>, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
diesel::update(
|
diesel::update(
|
||||||
person_mention
|
person_mention::table
|
||||||
.filter(recipient_id.eq(for_recipient_id))
|
.filter(person_mention::recipient_id.eq(for_recipient_id))
|
||||||
.filter(read.eq(false)),
|
.filter(person_mention::read.eq(false)),
|
||||||
)
|
)
|
||||||
.set(read.eq(true))
|
.set(person_mention::read.eq(true))
|
||||||
.get_results::<Self>(conn)
|
.get_results::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
|
@ -65,18 +65,18 @@ impl PersonMention {
|
||||||
for_recipient_id: PersonId,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let conn = &mut get_conn(pool).await?;
|
let conn = &mut get_conn(pool).await?;
|
||||||
person_mention
|
person_mention::table
|
||||||
.filter(comment_id.eq(for_comment_id))
|
.filter(person_mention::comment_id.eq(for_comment_id))
|
||||||
.filter(recipient_id.eq(for_recipient_id))
|
.filter(person_mention::recipient_id.eq(for_recipient_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -362,9 +362,9 @@ impl PostHide {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -80,9 +80,9 @@ impl Reportable for PostReport {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
|
|
@ -74,9 +74,9 @@ impl PrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
source::{
|
source::{
|
||||||
|
|
|
@ -2,16 +2,27 @@ use crate::newtypes::{DbUrl, LocalUserId};
|
||||||
#[cfg(feature = "full")]
|
#[cfg(feature = "full")]
|
||||||
use crate::schema::{local_image, remote_image};
|
use crate::schema::{local_image, remote_image};
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use serde_with::skip_serializing_none;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
#[cfg(feature = "full")]
|
||||||
|
use ts_rs::TS;
|
||||||
use typed_builder::TypedBuilder;
|
use typed_builder::TypedBuilder;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Debug, Clone)]
|
#[skip_serializing_none]
|
||||||
#[cfg_attr(feature = "full", derive(Queryable, Associations))]
|
#[derive(Clone, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||||
|
#[cfg_attr(
|
||||||
|
feature = "full",
|
||||||
|
derive(Queryable, Selectable, Identifiable, Associations, TS)
|
||||||
|
)]
|
||||||
|
#[cfg_attr(feature = "full", ts(export))]
|
||||||
#[cfg_attr(feature = "full", diesel(table_name = local_image))]
|
#[cfg_attr(feature = "full", diesel(table_name = local_image))]
|
||||||
#[cfg_attr(
|
#[cfg_attr(
|
||||||
feature = "full",
|
feature = "full",
|
||||||
diesel(belongs_to(crate::source::local_user::LocalUser))
|
diesel(belongs_to(crate::source::local_user::LocalUser))
|
||||||
)]
|
)]
|
||||||
|
#[cfg_attr(feature = "full", diesel(check_for_backend(diesel::pg::Pg)))]
|
||||||
|
#[cfg_attr(feature = "full", diesel(primary_key(local_user_id)))]
|
||||||
pub struct LocalImage {
|
pub struct LocalImage {
|
||||||
pub local_user_id: Option<LocalUserId>,
|
pub local_user_id: Option<LocalUserId>,
|
||||||
pub pictrs_alias: String,
|
pub pictrs_alias: String,
|
||||||
|
|
|
@ -536,9 +536,9 @@ impl<RF, LF> Queries<RF, LF> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -258,9 +258,9 @@ impl CommentReportQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
comment_report_view::{CommentReportQuery, CommentReportView},
|
comment_report_view::{CommentReportQuery, CommentReportView},
|
||||||
|
@ -308,7 +308,9 @@ mod tests {
|
||||||
.person_id(inserted_timmy.id)
|
.person_id(inserted_timmy.id)
|
||||||
.password_encrypted("123".to_string())
|
.password_encrypted("123".to_string())
|
||||||
.build();
|
.build();
|
||||||
let timmy_local_user = LocalUser::create(pool, &new_local_user).await.unwrap();
|
let timmy_local_user = LocalUser::create(pool, &new_local_user, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let timmy_view = LocalUserView {
|
let timmy_view = LocalUserView {
|
||||||
local_user: timmy_local_user,
|
local_user: timmy_local_user,
|
||||||
local_user_vote_display_mode: LocalUserVoteDisplayMode::default(),
|
local_user_vote_display_mode: LocalUserVoteDisplayMode::default(),
|
||||||
|
|
|
@ -426,9 +426,9 @@ impl<'a> CommentQuery<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
comment_view::{CommentQuery, CommentSortType, CommentView, DbPool},
|
comment_view::{CommentQuery, CommentSortType, CommentView, DbPool},
|
||||||
|
@ -503,7 +503,7 @@ mod tests {
|
||||||
.admin(Some(true))
|
.admin(Some(true))
|
||||||
.password_encrypted(String::new())
|
.password_encrypted(String::new())
|
||||||
.build();
|
.build();
|
||||||
let inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
|
let inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form, vec![])
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -1183,6 +1183,7 @@ mod tests {
|
||||||
let inserted_banned_from_comm_local_user = LocalUser::create(
|
let inserted_banned_from_comm_local_user = LocalUser::create(
|
||||||
pool,
|
pool,
|
||||||
&LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
|
&LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -283,9 +283,9 @@ impl PostReportQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
post_report_view::{PostReportQuery, PostReportView},
|
post_report_view::{PostReportQuery, PostReportView},
|
||||||
|
@ -330,7 +330,9 @@ mod tests {
|
||||||
.person_id(inserted_timmy.id)
|
.person_id(inserted_timmy.id)
|
||||||
.password_encrypted("123".to_string())
|
.password_encrypted("123".to_string())
|
||||||
.build();
|
.build();
|
||||||
let timmy_local_user = LocalUser::create(pool, &new_local_user).await.unwrap();
|
let timmy_local_user = LocalUser::create(pool, &new_local_user, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
let timmy_view = LocalUserView {
|
let timmy_view = LocalUserView {
|
||||||
local_user: timmy_local_user,
|
local_user: timmy_local_user,
|
||||||
local_user_vote_display_mode: LocalUserVoteDisplayMode::default(),
|
local_user_vote_display_mode: LocalUserVoteDisplayMode::default(),
|
||||||
|
|
|
@ -829,7 +829,7 @@ mod tests {
|
||||||
admin: Some(true),
|
admin: Some(true),
|
||||||
..LocalUserInsertForm::test_form(inserted_person.id)
|
..LocalUserInsertForm::test_form(inserted_person.id)
|
||||||
};
|
};
|
||||||
let inserted_local_user = LocalUser::create(pool, &local_user_form).await?;
|
let inserted_local_user = LocalUser::create(pool, &local_user_form, vec![]).await?;
|
||||||
|
|
||||||
let new_bot = PersonInsertForm {
|
let new_bot = PersonInsertForm {
|
||||||
bot_account: Some(true),
|
bot_account: Some(true),
|
||||||
|
@ -855,6 +855,7 @@ mod tests {
|
||||||
let inserted_blocked_local_user = LocalUser::create(
|
let inserted_blocked_local_user = LocalUser::create(
|
||||||
pool,
|
pool,
|
||||||
&LocalUserInsertForm::test_form(inserted_blocked_person.id),
|
&LocalUserInsertForm::test_form(inserted_blocked_person.id),
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -1746,6 +1747,7 @@ mod tests {
|
||||||
let inserted_banned_from_comm_local_user = LocalUser::create(
|
let inserted_banned_from_comm_local_user = LocalUser::create(
|
||||||
pool,
|
pool,
|
||||||
&LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
|
&LocalUserInsertForm::test_form(inserted_banned_from_comm_person.id),
|
||||||
|
vec![],
|
||||||
)
|
)
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
|
|
@ -106,9 +106,9 @@ impl PrivateMessageReportQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::private_message_report_view::PrivateMessageReportQuery;
|
use crate::private_message_report_view::PrivateMessageReportQuery;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
|
|
@ -173,9 +173,9 @@ impl PrivateMessageQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{private_message_view::PrivateMessageQuery, structs::PrivateMessageView};
|
use crate::{private_message_view::PrivateMessageQuery, structs::PrivateMessageView};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
|
|
@ -127,9 +127,9 @@ impl RegistrationApplicationQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::registration_application_view::{
|
use crate::registration_application_view::{
|
||||||
RegistrationApplicationQuery,
|
RegistrationApplicationQuery,
|
||||||
|
@ -176,7 +176,7 @@ mod tests {
|
||||||
.admin(Some(true))
|
.admin(Some(true))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form)
|
let _inserted_timmy_local_user = LocalUser::create(pool, &timmy_local_user_form, vec![])
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ mod tests {
|
||||||
.password_encrypted("nada".to_string())
|
.password_encrypted("nada".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form)
|
let inserted_sara_local_user = LocalUser::create(pool, &sara_local_user_form, vec![])
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
@ -224,7 +224,7 @@ mod tests {
|
||||||
.password_encrypted("nada".to_string())
|
.password_encrypted("nada".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form)
|
let inserted_jess_local_user = LocalUser::create(pool, &jess_local_user_form, vec![])
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|
|
@ -211,5 +211,6 @@ pub struct CustomEmojiView {
|
||||||
/// A vote view for checking a post or comments votes.
|
/// A vote view for checking a post or comments votes.
|
||||||
pub struct VoteView {
|
pub struct VoteView {
|
||||||
pub creator: Person,
|
pub creator: Person,
|
||||||
|
pub creator_banned_from_community: bool,
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,16 @@
|
||||||
use crate::structs::VoteView;
|
use crate::structs::VoteView;
|
||||||
use diesel::{result::Error, ExpressionMethods, QueryDsl};
|
use diesel::{
|
||||||
|
result::Error,
|
||||||
|
BoolExpressionMethods,
|
||||||
|
ExpressionMethods,
|
||||||
|
JoinOnDsl,
|
||||||
|
NullableExpressionMethods,
|
||||||
|
QueryDsl,
|
||||||
|
};
|
||||||
use diesel_async::RunQueryDsl;
|
use diesel_async::RunQueryDsl;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
newtypes::{CommentId, PostId},
|
newtypes::{CommentId, PostId},
|
||||||
schema::{comment_like, person, post_like},
|
schema::{comment_like, community_person_ban, person, post, post_like},
|
||||||
utils::{get_conn, limit_and_offset, DbPool},
|
utils::{get_conn, limit_and_offset, DbPool},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -19,8 +26,21 @@ impl VoteView {
|
||||||
|
|
||||||
post_like::table
|
post_like::table
|
||||||
.inner_join(person::table)
|
.inner_join(person::table)
|
||||||
|
.inner_join(post::table)
|
||||||
|
// Join to community_person_ban to get creator_banned_from_community
|
||||||
|
.left_join(
|
||||||
|
community_person_ban::table.on(
|
||||||
|
post::community_id
|
||||||
|
.eq(community_person_ban::community_id)
|
||||||
|
.and(community_person_ban::person_id.eq(post_like::person_id)),
|
||||||
|
),
|
||||||
|
)
|
||||||
.filter(post_like::post_id.eq(post_id))
|
.filter(post_like::post_id.eq(post_id))
|
||||||
.select((person::all_columns, post_like::score))
|
.select((
|
||||||
|
person::all_columns,
|
||||||
|
community_person_ban::community_id.nullable().is_not_null(),
|
||||||
|
post_like::score,
|
||||||
|
))
|
||||||
.order_by(post_like::score)
|
.order_by(post_like::score)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
|
@ -39,8 +59,21 @@ impl VoteView {
|
||||||
|
|
||||||
comment_like::table
|
comment_like::table
|
||||||
.inner_join(person::table)
|
.inner_join(person::table)
|
||||||
|
.inner_join(post::table)
|
||||||
|
// Join to community_person_ban to get creator_banned_from_community
|
||||||
|
.left_join(
|
||||||
|
community_person_ban::table.on(
|
||||||
|
post::community_id
|
||||||
|
.eq(community_person_ban::community_id)
|
||||||
|
.and(community_person_ban::person_id.eq(comment_like::person_id)),
|
||||||
|
),
|
||||||
|
)
|
||||||
.filter(comment_like::comment_id.eq(comment_id))
|
.filter(comment_like::comment_id.eq(comment_id))
|
||||||
.select((person::all_columns, comment_like::score))
|
.select((
|
||||||
|
person::all_columns,
|
||||||
|
community_person_ban::community_id.nullable().is_not_null(),
|
||||||
|
comment_like::score,
|
||||||
|
))
|
||||||
.order_by(comment_like::score)
|
.order_by(comment_like::score)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.offset(offset)
|
.offset(offset)
|
||||||
|
@ -50,20 +83,20 @@ impl VoteView {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::structs::VoteView;
|
use crate::structs::VoteView;
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
source::{
|
source::{
|
||||||
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
comment::{Comment, CommentInsertForm, CommentLike, CommentLikeForm},
|
||||||
community::{Community, CommunityInsertForm},
|
community::{Community, CommunityInsertForm, CommunityPersonBan, CommunityPersonBanForm},
|
||||||
instance::Instance,
|
instance::Instance,
|
||||||
person::{Person, PersonInsertForm},
|
person::{Person, PersonInsertForm},
|
||||||
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
post::{Post, PostInsertForm, PostLike, PostLikeForm},
|
||||||
},
|
},
|
||||||
traits::{Crud, Likeable},
|
traits::{Bannable, Crud, Likeable},
|
||||||
utils::build_db_pool_for_tests,
|
utils::build_db_pool_for_tests,
|
||||||
};
|
};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
@ -139,10 +172,12 @@ mod tests {
|
||||||
let expected_post_vote_views = [
|
let expected_post_vote_views = [
|
||||||
VoteView {
|
VoteView {
|
||||||
creator: inserted_sara.clone(),
|
creator: inserted_sara.clone(),
|
||||||
|
creator_banned_from_community: false,
|
||||||
score: -1,
|
score: -1,
|
||||||
},
|
},
|
||||||
VoteView {
|
VoteView {
|
||||||
creator: inserted_timmy.clone(),
|
creator: inserted_timmy.clone(),
|
||||||
|
creator_banned_from_community: false,
|
||||||
score: 1,
|
score: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -177,10 +212,12 @@ mod tests {
|
||||||
let expected_comment_vote_views = [
|
let expected_comment_vote_views = [
|
||||||
VoteView {
|
VoteView {
|
||||||
creator: inserted_timmy.clone(),
|
creator: inserted_timmy.clone(),
|
||||||
|
creator_banned_from_community: false,
|
||||||
score: -1,
|
score: -1,
|
||||||
},
|
},
|
||||||
VoteView {
|
VoteView {
|
||||||
creator: inserted_sara.clone(),
|
creator: inserted_sara.clone(),
|
||||||
|
creator_banned_from_community: false,
|
||||||
score: 1,
|
score: 1,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -190,6 +227,41 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(read_comment_vote_views, expected_comment_vote_views);
|
assert_eq!(read_comment_vote_views, expected_comment_vote_views);
|
||||||
|
|
||||||
|
// Ban timmy from that community
|
||||||
|
let ban_timmy_form = CommunityPersonBanForm {
|
||||||
|
community_id: inserted_community.id,
|
||||||
|
person_id: inserted_timmy.id,
|
||||||
|
expires: None,
|
||||||
|
};
|
||||||
|
CommunityPersonBan::ban(pool, &ban_timmy_form)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Make sure creator_banned_from_community is true
|
||||||
|
let read_comment_vote_views_after_ban =
|
||||||
|
VoteView::list_for_comment(pool, inserted_comment.id, None, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
read_comment_vote_views_after_ban
|
||||||
|
.first()
|
||||||
|
.unwrap()
|
||||||
|
.creator_banned_from_community
|
||||||
|
);
|
||||||
|
|
||||||
|
let read_post_vote_views_after_ban =
|
||||||
|
VoteView::list_for_post(pool, inserted_post.id, None, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
read_post_vote_views_after_ban
|
||||||
|
.get(1)
|
||||||
|
.unwrap()
|
||||||
|
.creator_banned_from_community
|
||||||
|
);
|
||||||
|
|
||||||
// Cleanup
|
// Cleanup
|
||||||
Instance::delete(pool, inserted_instance.id).await.unwrap();
|
Instance::delete(pool, inserted_instance.id).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,16 @@ fn queries<'a>() -> Queries<
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let is_local_user_banned_from_community = |person_id| {
|
||||||
|
exists(
|
||||||
|
community_person_ban::table.filter(
|
||||||
|
community::id
|
||||||
|
.eq(community_person_ban::community_id)
|
||||||
|
.and(community_person_ban::person_id.eq(person_id)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let is_saved = |person_id| {
|
let is_saved = |person_id| {
|
||||||
exists(
|
exists(
|
||||||
comment_saved::table.filter(
|
comment_saved::table.filter(
|
||||||
|
@ -107,6 +117,14 @@ fn queries<'a>() -> Queries<
|
||||||
|
|
||||||
let all_joins = move |query: comment_reply::BoxedQuery<'a, Pg>,
|
let all_joins = move |query: comment_reply::BoxedQuery<'a, Pg>,
|
||||||
my_person_id: Option<PersonId>| {
|
my_person_id: Option<PersonId>| {
|
||||||
|
let is_local_user_banned_from_community_selection: Box<
|
||||||
|
dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>,
|
||||||
|
> = if let Some(person_id) = my_person_id {
|
||||||
|
Box::new(is_local_user_banned_from_community(person_id))
|
||||||
|
} else {
|
||||||
|
Box::new(false.into_sql::<sql_types::Bool>())
|
||||||
|
};
|
||||||
|
|
||||||
let score_selection: Box<
|
let score_selection: Box<
|
||||||
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
|
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
|
||||||
> = if let Some(person_id) = my_person_id {
|
> = if let Some(person_id) = my_person_id {
|
||||||
|
@ -153,6 +171,7 @@ fn queries<'a>() -> Queries<
|
||||||
aliases::person1.fields(person::all_columns),
|
aliases::person1.fields(person::all_columns),
|
||||||
comment_aggregates::all_columns,
|
comment_aggregates::all_columns,
|
||||||
is_creator_banned_from_community,
|
is_creator_banned_from_community,
|
||||||
|
is_local_user_banned_from_community_selection,
|
||||||
creator_is_moderator,
|
creator_is_moderator,
|
||||||
creator_is_admin,
|
creator_is_admin,
|
||||||
subscribed_type_selection,
|
subscribed_type_selection,
|
||||||
|
|
|
@ -250,9 +250,9 @@ impl<'a> CommunityQuery<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{community_view::CommunityQuery, structs::CommunityView};
|
use crate::{community_view::CommunityQuery, structs::CommunityView};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
|
@ -296,7 +296,9 @@ mod tests {
|
||||||
.person_id(inserted_person.id)
|
.person_id(inserted_person.id)
|
||||||
.password_encrypted(String::new())
|
.password_encrypted(String::new())
|
||||||
.build();
|
.build();
|
||||||
let local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
|
let local_user = LocalUser::create(pool, &local_user_form, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let new_community = CommunityInsertForm::builder()
|
let new_community = CommunityInsertForm::builder()
|
||||||
.name("test_community_3".to_string())
|
.name("test_community_3".to_string())
|
||||||
|
|
|
@ -47,6 +47,16 @@ fn queries<'a>() -> Queries<
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let is_local_user_banned_from_community = |person_id| {
|
||||||
|
exists(
|
||||||
|
community_person_ban::table.filter(
|
||||||
|
community::id
|
||||||
|
.eq(community_person_ban::community_id)
|
||||||
|
.and(community_person_ban::person_id.eq(person_id)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
let is_saved = |person_id| {
|
let is_saved = |person_id| {
|
||||||
exists(
|
exists(
|
||||||
comment_saved::table.filter(
|
comment_saved::table.filter(
|
||||||
|
@ -107,6 +117,13 @@ fn queries<'a>() -> Queries<
|
||||||
|
|
||||||
let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>,
|
let all_joins = move |query: person_mention::BoxedQuery<'a, Pg>,
|
||||||
my_person_id: Option<PersonId>| {
|
my_person_id: Option<PersonId>| {
|
||||||
|
let is_local_user_banned_from_community_selection: Box<
|
||||||
|
dyn BoxableExpression<_, Pg, SqlType = sql_types::Bool>,
|
||||||
|
> = if let Some(person_id) = my_person_id {
|
||||||
|
Box::new(is_local_user_banned_from_community(person_id))
|
||||||
|
} else {
|
||||||
|
Box::new(false.into_sql::<sql_types::Bool>())
|
||||||
|
};
|
||||||
let score_selection: Box<
|
let score_selection: Box<
|
||||||
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
|
dyn BoxableExpression<_, Pg, SqlType = sql_types::Nullable<sql_types::SmallInt>>,
|
||||||
> = if let Some(person_id) = my_person_id {
|
> = if let Some(person_id) = my_person_id {
|
||||||
|
@ -153,6 +170,7 @@ fn queries<'a>() -> Queries<
|
||||||
aliases::person1.fields(person::all_columns),
|
aliases::person1.fields(person::all_columns),
|
||||||
comment_aggregates::all_columns,
|
comment_aggregates::all_columns,
|
||||||
is_creator_banned_from_community,
|
is_creator_banned_from_community,
|
||||||
|
is_local_user_banned_from_community_selection,
|
||||||
creator_is_moderator,
|
creator_is_moderator,
|
||||||
creator_is_admin,
|
creator_is_admin,
|
||||||
subscribed_type_selection,
|
subscribed_type_selection,
|
||||||
|
|
|
@ -163,9 +163,9 @@ impl PersonQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use diesel::NotFound;
|
use diesel::NotFound;
|
||||||
|
@ -204,7 +204,7 @@ mod tests {
|
||||||
.person_id(alice.id)
|
.person_id(alice.id)
|
||||||
.password_encrypted(String::new())
|
.password_encrypted(String::new())
|
||||||
.build();
|
.build();
|
||||||
let alice_local_user = LocalUser::create(pool, &alice_local_user_form).await?;
|
let alice_local_user = LocalUser::create(pool, &alice_local_user_form, vec![]).await?;
|
||||||
|
|
||||||
let bob_form = PersonInsertForm::builder()
|
let bob_form = PersonInsertForm::builder()
|
||||||
.name("bob".to_string())
|
.name("bob".to_string())
|
||||||
|
@ -218,7 +218,7 @@ mod tests {
|
||||||
.person_id(bob.id)
|
.person_id(bob.id)
|
||||||
.password_encrypted(String::new())
|
.password_encrypted(String::new())
|
||||||
.build();
|
.build();
|
||||||
let bob_local_user = LocalUser::create(pool, &bob_local_user_form).await?;
|
let bob_local_user = LocalUser::create(pool, &bob_local_user_form, vec![]).await?;
|
||||||
|
|
||||||
Ok(Data {
|
Ok(Data {
|
||||||
alice,
|
alice,
|
||||||
|
|
|
@ -108,6 +108,7 @@ pub struct PersonMentionView {
|
||||||
pub recipient: Person,
|
pub recipient: Person,
|
||||||
pub counts: CommentAggregates,
|
pub counts: CommentAggregates,
|
||||||
pub creator_banned_from_community: bool,
|
pub creator_banned_from_community: bool,
|
||||||
|
pub banned_from_community: bool,
|
||||||
pub creator_is_moderator: bool,
|
pub creator_is_moderator: bool,
|
||||||
pub creator_is_admin: bool,
|
pub creator_is_admin: bool,
|
||||||
pub subscribed: SubscribedType,
|
pub subscribed: SubscribedType,
|
||||||
|
@ -131,6 +132,7 @@ pub struct CommentReplyView {
|
||||||
pub recipient: Person,
|
pub recipient: Person,
|
||||||
pub counts: CommentAggregates,
|
pub counts: CommentAggregates,
|
||||||
pub creator_banned_from_community: bool,
|
pub creator_banned_from_community: bool,
|
||||||
|
pub banned_from_community: bool,
|
||||||
pub creator_is_moderator: bool,
|
pub creator_is_moderator: bool,
|
||||||
pub creator_is_admin: bool,
|
pub creator_is_admin: bool,
|
||||||
pub subscribed: SubscribedType,
|
pub subscribed: SubscribedType,
|
||||||
|
|
|
@ -221,9 +221,9 @@ fn parse_ip(addr: &str) -> Option<IpAddr> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_ip() {
|
fn test_parse_ip() {
|
||||||
|
|
|
@ -158,7 +158,7 @@ impl<K: Eq + Hash, C: MapLevel> MapLevel for Map<K, C> {
|
||||||
|
|
||||||
// Evaluated if `some_children_remaining` is false
|
// Evaluated if `some_children_remaining` is false
|
||||||
let total_has_refill_in_future = || {
|
let total_has_refill_in_future = || {
|
||||||
group.total.into_iter().all(|(action_type, bucket)| {
|
group.total.into_iter().any(|(action_type, bucket)| {
|
||||||
#[allow(clippy::indexing_slicing)]
|
#[allow(clippy::indexing_slicing)]
|
||||||
let config = configs[action_type];
|
let config = configs[action_type];
|
||||||
bucket.update(now, config).tokens != config.capacity
|
bucket.update(now, config).tokens != config.capacity
|
||||||
|
@ -306,9 +306,9 @@ fn split_ipv6(ip: Ipv6Addr) -> ([u8; 6], u8, u8) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::{ActionType, BucketConfig, InstantSecs, RateLimitState, RateLimitedGroup};
|
use super::{ActionType, BucketConfig, InstantSecs, RateLimitState, RateLimitedGroup};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
@ -416,5 +416,23 @@ mod tests {
|
||||||
rate_limiter.remove_full_buckets(now);
|
rate_limiter.remove_full_buckets(now);
|
||||||
assert!(rate_limiter.ipv4_buckets.is_empty());
|
assert!(rate_limiter.ipv4_buckets.is_empty());
|
||||||
assert!(rate_limiter.ipv6_buckets.is_empty());
|
assert!(rate_limiter.ipv6_buckets.is_empty());
|
||||||
|
|
||||||
|
// `remove full buckets` should not remove empty buckets
|
||||||
|
let ip = "1.1.1.1".parse().unwrap();
|
||||||
|
// empty the bucket with 2 requests
|
||||||
|
assert!(rate_limiter.check(ActionType::Post, ip, now));
|
||||||
|
assert!(rate_limiter.check(ActionType::Post, ip, now));
|
||||||
|
|
||||||
|
rate_limiter.remove_full_buckets(now);
|
||||||
|
assert!(!rate_limiter.ipv4_buckets.is_empty());
|
||||||
|
|
||||||
|
// `remove full buckets` should not remove partial buckets
|
||||||
|
now.secs += 2;
|
||||||
|
let ip = "1.1.1.1".parse().unwrap();
|
||||||
|
// Only make one request, so bucket still has 1 token
|
||||||
|
assert!(rate_limiter.check(ActionType::Post, ip, now));
|
||||||
|
|
||||||
|
rate_limiter.remove_full_buckets(now);
|
||||||
|
assert!(!rate_limiter.ipv4_buckets.is_empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,9 +107,9 @@ pub fn markdown_check_for_blocked_urls(text: &str, blocklist: &RegexSet) -> Lemm
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -134,9 +134,9 @@ pub fn add(markdown_parser: &mut MarkdownIt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::utils::markdown::spoiler_rule::add;
|
use crate::utils::markdown::spoiler_rule::add;
|
||||||
use markdown_it::MarkdownIt;
|
use markdown_it::MarkdownIt;
|
||||||
|
|
|
@ -34,9 +34,9 @@ pub fn scrape_text_for_mentions(text: &str) -> Vec<MentionData> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod test {
|
mod test {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::utils::mention::scrape_text_for_mentions;
|
use crate::utils::mention::scrape_text_for_mentions;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -64,9 +64,9 @@ pub(crate) fn slurs_vec_to_str(slurs: &[&str]) -> String {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod test {
|
mod test {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::utils::slurs::{remove_slurs, slur_check, slurs_vec_to_str};
|
use crate::utils::slurs::{remove_slurs, slur_check, slurs_vec_to_str};
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -327,9 +327,9 @@ pub fn check_urls_are_valid(urls: &Vec<String>) -> LemmyResult<Vec<String>> {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
error::LemmyErrorType,
|
error::LemmyErrorType,
|
||||||
|
|
|
@ -29,6 +29,7 @@ use lemmy_api::{
|
||||||
get_captcha::get_captcha,
|
get_captcha::get_captcha,
|
||||||
list_banned::list_banned_users,
|
list_banned::list_banned_users,
|
||||||
list_logins::list_logins,
|
list_logins::list_logins,
|
||||||
|
list_media::list_media,
|
||||||
login::login,
|
login::login,
|
||||||
logout::logout,
|
logout::logout,
|
||||||
notifications::{
|
notifications::{
|
||||||
|
@ -71,6 +72,7 @@ use lemmy_api::{
|
||||||
block::block_instance,
|
block::block_instance,
|
||||||
federated_instances::get_federated_instances,
|
federated_instances::get_federated_instances,
|
||||||
leave_admin::leave_admin,
|
leave_admin::leave_admin,
|
||||||
|
list_all_media::list_all_media,
|
||||||
mod_log::get_mod_log,
|
mod_log::get_mod_log,
|
||||||
purge::{
|
purge::{
|
||||||
comment::purge_comment,
|
comment::purge_comment,
|
||||||
|
@ -282,6 +284,12 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
.wrap(rate_limit.import_user_settings())
|
.wrap(rate_limit.import_user_settings())
|
||||||
.route(web::post().to(import_settings)),
|
.route(web::post().to(import_settings)),
|
||||||
)
|
)
|
||||||
|
// TODO, all the current account related actions under /user need to get moved here eventually
|
||||||
|
.service(
|
||||||
|
web::scope("/account")
|
||||||
|
.wrap(rate_limit.message())
|
||||||
|
.route("/list_media", web::get().to(list_media)),
|
||||||
|
)
|
||||||
// User actions
|
// User actions
|
||||||
.service(
|
.service(
|
||||||
web::scope("/user")
|
web::scope("/user")
|
||||||
|
@ -339,6 +347,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimitCell) {
|
||||||
"/registration_application/approve",
|
"/registration_application/approve",
|
||||||
web::put().to(approve_registration_application),
|
web::put().to(approve_registration_application),
|
||||||
)
|
)
|
||||||
|
.route("/list_all_media", web::get().to(list_all_media))
|
||||||
.service(
|
.service(
|
||||||
web::scope("/purge")
|
web::scope("/purge")
|
||||||
.route("/person", web::post().to(purge_person))
|
.route("/person", web::post().to(purge_person))
|
||||||
|
|
|
@ -475,7 +475,7 @@ async fn initialize_local_site_2022_10_10(
|
||||||
.email(setup.admin_email.clone())
|
.email(setup.admin_email.clone())
|
||||||
.admin(Some(true))
|
.admin(Some(true))
|
||||||
.build();
|
.build();
|
||||||
LocalUser::create(pool, &local_user_form).await?;
|
LocalUser::create(pool, &local_user_form, vec![]).await?;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Add an entry for the site table
|
// Add an entry for the site table
|
||||||
|
|
|
@ -517,9 +517,9 @@ async fn update_instance_software(
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use lemmy_routes::nodeinfo::NodeInfo;
|
use lemmy_routes::nodeinfo::NodeInfo;
|
||||||
use pretty_assertions::assert_eq;
|
use pretty_assertions::assert_eq;
|
||||||
|
|
|
@ -98,9 +98,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::unwrap_used)]
|
||||||
|
#[allow(clippy::indexing_slicing)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#![allow(clippy::unwrap_used)]
|
|
||||||
#![allow(clippy::indexing_slicing)]
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
use actix_web::test::TestRequest;
|
use actix_web::test::TestRequest;
|
||||||
|
@ -155,7 +155,9 @@ mod tests {
|
||||||
.password_encrypted("123456".to_string())
|
.password_encrypted("123456".to_string())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let inserted_local_user = LocalUser::create(pool, &local_user_form).await.unwrap();
|
let inserted_local_user = LocalUser::create(pool, &local_user_form, vec![])
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
let req = TestRequest::default().to_http_request();
|
let req = TestRequest::default().to_http_request();
|
||||||
let jwt = Claims::generate(inserted_local_user.id, req, &context)
|
let jwt = Claims::generate(inserted_local_user.id, req, &context)
|
||||||
|
|
Loading…
Reference in a new issue