Compare commits
61 commits
upgrade-ru
...
main
Author | SHA1 | Date | |
---|---|---|---|
f55ef1d7ef | |||
14bc9f0946 | |||
493598c1ba | |||
96efe302ce | |||
e25bcb35d7 | |||
05b485b678 | |||
360d4ea8d1 | |||
c06d612432 | |||
c88722983e | |||
33a326854a | |||
9930c7288a | |||
8d9fab0389 | |||
c3efb9f7cf | |||
5899b89ef2 | |||
99e5a4d1c3 | |||
|
db4fe8031c | ||
270ce539bf | |||
b9f483bc27 | |||
8ee624a542 | |||
621355b6ef | |||
72b5e0cab5 | |||
|
74272ed754 | ||
|
4426c3176d | ||
|
7b0a09e84e | ||
|
ab947f1f08 | ||
5998c83b2a | |||
434fb53dd1 | |||
75a95acf04 | |||
|
931a132161 | ||
0a7271a185 | |||
7c039340ed | |||
7d04f371a5 | |||
5d8ccbafe4 | |||
1a4c8c08ee | |||
9cb4dad4b4 | |||
ddf4a667b1 | |||
|
fc74bfeb23 | ||
8f6b8895f4 | |||
|
a650312858 | ||
ff2c71a74a | |||
|
126c6a23bb | ||
e0c61c1334 | |||
f7aa97d45e | |||
a1c7584875 | |||
817b4ff08e | |||
ca3c1269f5 | |||
|
0a52396706 | ||
|
7c4969c92b | ||
|
45a94203f2 | ||
7189328f80 | |||
|
134fece36d | ||
985dbcaada | |||
|
e78ba38e94 | ||
7f56281c26 | |||
|
45e05dac30 | ||
a869a2823b | |||
efc9047f87 | |||
aba32917bd | |||
a183815870 | |||
d0bd02eea0 | |||
5a33fce8bd |
168 changed files with 5521 additions and 4061 deletions
15
.drone.yml
15
.drone.yml
|
@ -21,14 +21,23 @@ steps:
|
||||||
|
|
||||||
- name: cargo clippy
|
- name: cargo clippy
|
||||||
image: ekidd/rust-musl-builder:1.50.0
|
image: ekidd/rust-musl-builder:1.50.0
|
||||||
|
environment:
|
||||||
|
CARGO_HOME: /drone/src/.cargo
|
||||||
commands:
|
commands:
|
||||||
|
- whoami
|
||||||
|
- ls -la ~/.cargo
|
||||||
|
- mv ~/.cargo .
|
||||||
|
- ls -la .cargo
|
||||||
- cargo clippy --workspace --tests --all-targets --all-features -- -D warnings -D deprecated -D clippy::perf -D clippy::complexity -D clippy::dbg_macro
|
- cargo clippy --workspace --tests --all-targets --all-features -- -D warnings -D deprecated -D clippy::perf -D clippy::complexity -D clippy::dbg_macro
|
||||||
|
- cargo clippy --workspace -- -D clippy::unwrap_used
|
||||||
|
|
||||||
- name: cargo test
|
- name: cargo test
|
||||||
image: ekidd/rust-musl-builder:1.50.0
|
image: ekidd/rust-musl-builder:1.50.0
|
||||||
environment:
|
environment:
|
||||||
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
|
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
|
||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
|
RUST_TEST_THREADS: 1
|
||||||
|
CARGO_HOME: /drone/src/.cargo
|
||||||
commands:
|
commands:
|
||||||
- sudo apt-get update
|
- sudo apt-get update
|
||||||
- sudo apt-get -y install --no-install-recommends espeak postgresql-client
|
- sudo apt-get -y install --no-install-recommends espeak postgresql-client
|
||||||
|
@ -36,6 +45,8 @@ steps:
|
||||||
|
|
||||||
- name: cargo build
|
- name: cargo build
|
||||||
image: ekidd/rust-musl-builder:1.50.0
|
image: ekidd/rust-musl-builder:1.50.0
|
||||||
|
environment:
|
||||||
|
CARGO_HOME: /drone/src/.cargo
|
||||||
commands:
|
commands:
|
||||||
- cargo build
|
- cargo build
|
||||||
- mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server
|
- mv target/x86_64-unknown-linux-musl/debug/lemmy_server target/lemmy_server
|
||||||
|
@ -106,6 +117,8 @@ steps:
|
||||||
environment:
|
environment:
|
||||||
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
|
LEMMY_DATABASE_URL: postgres://lemmy:password@database:5432/lemmy
|
||||||
RUST_BACKTRACE: 1
|
RUST_BACKTRACE: 1
|
||||||
|
RUST_TEST_THREADS: 1
|
||||||
|
CARGO_HOME: /drone/src/.cargo
|
||||||
commands:
|
commands:
|
||||||
- apt-get update
|
- apt-get update
|
||||||
- apt-get -y install --no-install-recommends espeak postgresql-client libssl-dev pkg-config libpq-dev
|
- apt-get -y install --no-install-recommends espeak postgresql-client libssl-dev pkg-config libpq-dev
|
||||||
|
@ -115,6 +128,8 @@ steps:
|
||||||
# Using Debian here because there seems to be no official Alpine-based Rust docker image for ARM.
|
# Using Debian here because there seems to be no official Alpine-based Rust docker image for ARM.
|
||||||
- name: cargo build
|
- name: cargo build
|
||||||
image: rust:1.50-slim-buster
|
image: rust:1.50-slim-buster
|
||||||
|
environment:
|
||||||
|
CARGO_HOME: /drone/src/.cargo
|
||||||
commands:
|
commands:
|
||||||
- apt-get update
|
- apt-get update
|
||||||
- apt-get -y install --no-install-recommends libssl-dev pkg-config libpq-dev
|
- apt-get -y install --no-install-recommends libssl-dev pkg-config libpq-dev
|
||||||
|
|
226
Cargo.lock
generated
226
Cargo.lock
generated
|
@ -144,8 +144,8 @@ version = "0.1.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
|
checksum = "b4ca8ce00b267af8ccebbd647de0d61e0674b6e61185cc7a592ff88772bed655"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -333,9 +333,9 @@ version = "0.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
|
checksum = "ad26f77093333e0e7c6ffe54ebe3582d908a104e448723eec6d43d08b07143fb"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -344,9 +344,9 @@ version = "0.5.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
|
checksum = "b95aceadaf327f18f0df5962fedc1bde2f870566a0b9f65c89508a3b1f79334c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -406,9 +406,9 @@ version = "0.1.42"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
|
checksum = "8d3a45e77e34375a7923b1e8febb049bb011f064714a8e17a1a616fef01da13d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -916,10 +916,10 @@ checksum = "f0c960ae2da4de88a91b2d920c2a7233b400bc33cb28453a2987822d8392519b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"fnv",
|
"fnv",
|
||||||
"ident_case",
|
"ident_case",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"strsim",
|
"strsim",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -929,8 +929,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling_core",
|
"darling_core",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -951,9 +951,9 @@ checksum = "a2658621297f2cf68762a6f7dc0bb7e1ff2cfd6583daef8ee0fed6f7ec468ec0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"derive_builder_core",
|
"derive_builder_core",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -963,9 +963,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
|
checksum = "2791ea3e372c8495c0bc2033991d76b512cd799d07491fbd6890124db9458bef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"darling",
|
"darling",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -974,9 +974,9 @@ version = "0.99.11"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1003,15 +1003,27 @@ dependencies = [
|
||||||
"serde_json",
|
"serde_json",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "diesel-derive-newtype"
|
||||||
|
version = "0.1.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e844e8e6f65dcf27aa0b97d4234f974d93dfbf56816033d71b5e0c7eb701709f"
|
||||||
|
dependencies = [
|
||||||
|
"diesel",
|
||||||
|
"proc-macro2 0.4.30",
|
||||||
|
"quote 0.6.13",
|
||||||
|
"syn 0.14.9",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "diesel_derives"
|
name = "diesel_derives"
|
||||||
version = "1.4.1"
|
version = "1.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
checksum = "45f5098f628d02a7a0f68ddba586fb61e80edec3bdc1be3b921f4ceec60858d3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1085,9 +1097,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
checksum = "7c5f0096a91d210159eceb2ff5e1c4da18388a170e1e3ce948aac9c8fdbbf595"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1253,9 +1265,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
|
checksum = "c287d25add322d9f9abdcdc5927ca398917996600182178774032e9f8258fedd"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -1852,6 +1864,7 @@ version = "0.1.0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"chrono",
|
"chrono",
|
||||||
"diesel",
|
"diesel",
|
||||||
|
"diesel-derive-newtype",
|
||||||
"log",
|
"log",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
@ -2144,9 +2157,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
|
checksum = "209d075476da2e63b4b29e72a2ef627b840589588e71400a25e3565c4f849d07"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error",
|
"proc-macro-error",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2165,9 +2178,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
checksum = "9753f12909fd8d923f75ae5c3258cae1ed3c8ec052e1b38c93c21a6d157f789c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"migrations_internals",
|
"migrations_internals",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2475,9 +2488,9 @@ checksum = "99b8db626e31e5b81787b9783425769681b347011cc59471e33ea46d2ea0cf55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"pest",
|
"pest",
|
||||||
"pest_meta",
|
"pest_meta",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2515,9 +2528,9 @@ version = "0.4.27"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
|
checksum = "65ad2ae56b6abe3a1ee25f15ee605bacadb9a764edaba9c2bf4103800d4a1895"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2526,9 +2539,9 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
|
checksum = "caa25a6393f22ce819b0f50e0be89287292fda8d425be38ee0ca14c4931d9e71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2589,9 +2602,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-error-attr",
|
"proc-macro-error-attr",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2601,8 +2614,8 @@ version = "1.0.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"version_check",
|
"version_check",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2618,13 +2631,22 @@ version = "0.1.7"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
checksum = "bc881b2c22681370c6a780e47af9840ef841837bc98118431d4e1868bd0c1086"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "proc-macro2"
|
||||||
|
version = "0.4.30"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759"
|
||||||
|
dependencies = [
|
||||||
|
"unicode-xid 0.1.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.24"
|
version = "1.0.24"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-xid",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2643,13 +2665,22 @@ dependencies = [
|
||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quote"
|
||||||
|
version = "0.6.13"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.8"
|
version = "1.0.8"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3032,9 +3063,9 @@ version = "1.0.123"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3078,9 +3109,9 @@ version = "0.5.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
|
checksum = "b2acd6defeddb41eb60bb468f8825d0cfd0c2a76bc03bfd235b6a1dc4f6a1ad5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3211,11 +3242,11 @@ version = "0.5.3"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3225,13 +3256,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base-x",
|
"base-x",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"sha1",
|
"sha1",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3259,9 +3290,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
|
checksum = "ee8bc6b87a5112aeeab1f4a9f7ab634fe6cbefc4850006df31267f4cfb9e3149"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck",
|
"heck",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "syn"
|
||||||
|
version = "0.14.9"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "261ae9ecaa397c42b960649561949d69311f08eeaea86a65696e6e46517cf741"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2 0.4.30",
|
||||||
|
"quote 0.6.13",
|
||||||
|
"unicode-xid 0.1.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3270,9 +3312,9 @@ version = "1.0.60"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"unicode-xid",
|
"unicode-xid 0.2.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3319,9 +3361,9 @@ version = "1.0.23"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
|
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3396,10 +3438,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
checksum = "e5c3be1edfad6027c69f5491cf4cb310d1a71ecd6af742788c6ff8bced86b8fa"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro-hack",
|
"proc-macro-hack",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"standback",
|
"standback",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -3635,6 +3677,12 @@ version = "1.7.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "unicode-xid"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "unicode-xid"
|
name = "unicode-xid"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
|
@ -3655,9 +3703,9 @@ checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "url"
|
name = "url"
|
||||||
version = "2.2.0"
|
version = "2.2.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "5909f2b0817350449ed73e8bcd81c8c3c8d9a7a5d8acba4b27db277f1868976e"
|
checksum = "9ccd964113622c8e9322cfac19eb1004a07e636c545f325da085d5cdde6f1f8b"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"form_urlencoded",
|
"form_urlencoded",
|
||||||
"idna",
|
"idna",
|
||||||
|
@ -3731,9 +3779,9 @@ dependencies = [
|
||||||
"bumpalo",
|
"bumpalo",
|
||||||
"lazy_static",
|
"lazy_static",
|
||||||
"log",
|
"log",
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3755,7 +3803,7 @@ version = "0.2.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"wasm-bindgen-macro-support",
|
"wasm-bindgen-macro-support",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -3765,9 +3813,9 @@ version = "0.2.70"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2 1.0.24",
|
||||||
"quote",
|
"quote 1.0.8",
|
||||||
"syn",
|
"syn 1.0.60",
|
||||||
"wasm-bindgen-backend",
|
"wasm-bindgen-backend",
|
||||||
"wasm-bindgen-shared",
|
"wasm-bindgen-shared",
|
||||||
]
|
]
|
||||||
|
|
|
@ -45,7 +45,7 @@ actix-web = { version = "3.3.2", default-features = false, features = ["rustls"]
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
env_logger = "0.8.2"
|
env_logger = "0.8.2"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||||
tokio = "0.3.6"
|
tokio = "0.3.6"
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
0.9.9
|
0.10.0-rc.7
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
version: '3.3'
|
version: '2.2'
|
||||||
|
|
||||||
services:
|
services:
|
||||||
lemmy:
|
lemmy:
|
||||||
|
@ -38,13 +38,14 @@ services:
|
||||||
restart: always
|
restart: always
|
||||||
|
|
||||||
pictrs:
|
pictrs:
|
||||||
image: asonix/pictrs:v0.2.5-r0
|
image: asonix/pictrs:v0.2.6-r1
|
||||||
user: 991:991
|
user: 991:991
|
||||||
ports:
|
ports:
|
||||||
- "127.0.0.1:8537:8080"
|
- "127.0.0.1:8537:8080"
|
||||||
volumes:
|
volumes:
|
||||||
- ./volumes/pictrs:/mnt
|
- ./volumes/pictrs:/mnt
|
||||||
restart: always
|
restart: always
|
||||||
|
mem_limit: 200m
|
||||||
|
|
||||||
iframely:
|
iframely:
|
||||||
image: dogbin/iframely:latest
|
image: dogbin/iframely:latest
|
||||||
|
@ -53,6 +54,7 @@ services:
|
||||||
volumes:
|
volumes:
|
||||||
- ./iframely.config.local.js:/iframely/config.local.js:ro
|
- ./iframely.config.local.js:/iframely/config.local.js:ro
|
||||||
restart: always
|
restart: always
|
||||||
|
mem_limit: 200m
|
||||||
|
|
||||||
postfix:
|
postfix:
|
||||||
image: mwader/postfix-relay
|
image: mwader/postfix-relay
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"eslint": "^7.18.0",
|
"eslint": "^7.18.0",
|
||||||
"eslint-plugin-jane": "^9.0.3",
|
"eslint-plugin-jane": "^9.0.3",
|
||||||
"jest": "^26.6.3",
|
"jest": "^26.6.3",
|
||||||
"lemmy-js-client": "0.9.1-rc.1",
|
"lemmy-js-client": "0.10.0-rc.4",
|
||||||
"node-fetch": "^2.6.1",
|
"node-fetch": "^2.6.1",
|
||||||
"prettier": "^2.1.2",
|
"prettier": "^2.1.2",
|
||||||
"ts-jest": "^26.4.4",
|
"ts-jest": "^26.4.4",
|
||||||
|
|
|
@ -33,9 +33,6 @@ function assertCommunityFederation(
|
||||||
);
|
);
|
||||||
expect(communityOne.creator.actor_id).toBe(communityTwo.creator.actor_id);
|
expect(communityOne.creator.actor_id).toBe(communityTwo.creator.actor_id);
|
||||||
expect(communityOne.community.nsfw).toBe(communityTwo.community.nsfw);
|
expect(communityOne.community.nsfw).toBe(communityTwo.community.nsfw);
|
||||||
expect(communityOne.community.category_id).toBe(
|
|
||||||
communityTwo.community.category_id
|
|
||||||
);
|
|
||||||
expect(communityOne.community.removed).toBe(communityTwo.community.removed);
|
expect(communityOne.community.removed).toBe(communityTwo.community.removed);
|
||||||
expect(communityOne.community.deleted).toBe(communityTwo.community.deleted);
|
expect(communityOne.community.deleted).toBe(communityTwo.community.deleted);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,9 +20,9 @@ import {
|
||||||
getPost,
|
getPost,
|
||||||
unfollowRemotes,
|
unfollowRemotes,
|
||||||
searchForUser,
|
searchForUser,
|
||||||
banUserFromSite,
|
banPersonFromSite,
|
||||||
searchPostLocal,
|
searchPostLocal,
|
||||||
banUserFromCommunity,
|
banPersonFromCommunity,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import { PostView, CommunityView } from 'lemmy-js-client';
|
import { PostView, CommunityView } from 'lemmy-js-client';
|
||||||
|
|
||||||
|
@ -305,7 +305,7 @@ test('Enforce site ban for federated user', async () => {
|
||||||
expect(alphaUser).toBeDefined();
|
expect(alphaUser).toBeDefined();
|
||||||
|
|
||||||
// ban alpha from beta site
|
// ban alpha from beta site
|
||||||
let banAlpha = await banUserFromSite(beta, alphaUser.user.id, true);
|
let banAlpha = await banPersonFromSite(beta, alphaUser.person.id, true);
|
||||||
expect(banAlpha.banned).toBe(true);
|
expect(banAlpha.banned).toBe(true);
|
||||||
|
|
||||||
// Alpha makes post on beta
|
// Alpha makes post on beta
|
||||||
|
@ -321,7 +321,7 @@ test('Enforce site ban for federated user', async () => {
|
||||||
expect(betaPost).toBeUndefined();
|
expect(betaPost).toBeUndefined();
|
||||||
|
|
||||||
// Unban alpha
|
// Unban alpha
|
||||||
let unBanAlpha = await banUserFromSite(beta, alphaUser.user.id, false);
|
let unBanAlpha = await banPersonFromSite(beta, alphaUser.person.id, false);
|
||||||
expect(unBanAlpha.banned).toBe(false);
|
expect(unBanAlpha.banned).toBe(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -332,8 +332,8 @@ test('Enforce community ban for federated user', async () => {
|
||||||
expect(alphaUser).toBeDefined();
|
expect(alphaUser).toBeDefined();
|
||||||
|
|
||||||
// ban alpha from beta site
|
// ban alpha from beta site
|
||||||
await banUserFromCommunity(beta, alphaUser.user.id, 2, false);
|
await banPersonFromCommunity(beta, alphaUser.person.id, 2, false);
|
||||||
let banAlpha = await banUserFromCommunity(beta, alphaUser.user.id, 2, true);
|
let banAlpha = await banPersonFromCommunity(beta, alphaUser.person.id, 2, true);
|
||||||
expect(banAlpha.banned).toBe(true);
|
expect(banAlpha.banned).toBe(true);
|
||||||
|
|
||||||
// Alpha makes post on beta
|
// Alpha makes post on beta
|
||||||
|
@ -349,9 +349,9 @@ test('Enforce community ban for federated user', async () => {
|
||||||
expect(betaPost).toBeUndefined();
|
expect(betaPost).toBeUndefined();
|
||||||
|
|
||||||
// Unban alpha
|
// Unban alpha
|
||||||
let unBanAlpha = await banUserFromCommunity(
|
let unBanAlpha = await banPersonFromCommunity(
|
||||||
beta,
|
beta,
|
||||||
alphaUser.user.id,
|
alphaUser.person.id,
|
||||||
2,
|
2,
|
||||||
false
|
false
|
||||||
);
|
);
|
||||||
|
|
|
@ -25,7 +25,7 @@ import {
|
||||||
CreateCommunity,
|
CreateCommunity,
|
||||||
DeleteCommunity,
|
DeleteCommunity,
|
||||||
RemoveCommunity,
|
RemoveCommunity,
|
||||||
GetUserMentions,
|
GetPersonMentions,
|
||||||
CreateCommentLike,
|
CreateCommentLike,
|
||||||
CreatePostLike,
|
CreatePostLike,
|
||||||
EditPrivateMessage,
|
EditPrivateMessage,
|
||||||
|
@ -36,15 +36,15 @@ import {
|
||||||
GetPost,
|
GetPost,
|
||||||
PrivateMessageResponse,
|
PrivateMessageResponse,
|
||||||
PrivateMessagesResponse,
|
PrivateMessagesResponse,
|
||||||
GetUserMentionsResponse,
|
GetPersonMentionsResponse,
|
||||||
SaveUserSettings,
|
SaveUserSettings,
|
||||||
SortType,
|
SortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
GetSiteResponse,
|
GetSiteResponse,
|
||||||
SearchType,
|
SearchType,
|
||||||
LemmyHttp,
|
LemmyHttp,
|
||||||
BanUserResponse,
|
BanPersonResponse,
|
||||||
BanUser,
|
BanPerson,
|
||||||
BanFromCommunity,
|
BanFromCommunity,
|
||||||
BanFromCommunityResponse,
|
BanFromCommunityResponse,
|
||||||
Post,
|
Post,
|
||||||
|
@ -289,32 +289,32 @@ export async function searchForUser(
|
||||||
return api.client.search(form);
|
return api.client.search(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function banUserFromSite(
|
export async function banPersonFromSite(
|
||||||
api: API,
|
api: API,
|
||||||
user_id: number,
|
person_id: number,
|
||||||
ban: boolean
|
ban: boolean
|
||||||
): Promise<BanUserResponse> {
|
): Promise<BanPersonResponse> {
|
||||||
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
|
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
|
||||||
// Use short-hand search url
|
// Use short-hand search url
|
||||||
let form: BanUser = {
|
let form: BanPerson = {
|
||||||
user_id,
|
person_id,
|
||||||
ban,
|
ban,
|
||||||
remove_data: false,
|
remove_data: false,
|
||||||
auth: api.auth,
|
auth: api.auth,
|
||||||
};
|
};
|
||||||
return api.client.banUser(form);
|
return api.client.banPerson(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function banUserFromCommunity(
|
export async function banPersonFromCommunity(
|
||||||
api: API,
|
api: API,
|
||||||
user_id: number,
|
person_id: number,
|
||||||
community_id: number,
|
community_id: number,
|
||||||
ban: boolean
|
ban: boolean
|
||||||
): Promise<BanFromCommunityResponse> {
|
): Promise<BanFromCommunityResponse> {
|
||||||
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
|
// Make sure lemmy-beta/c/main is cached on lemmy_alpha
|
||||||
// Use short-hand search url
|
// Use short-hand search url
|
||||||
let form: BanFromCommunity = {
|
let form: BanFromCommunity = {
|
||||||
user_id,
|
person_id,
|
||||||
community_id,
|
community_id,
|
||||||
remove_data: false,
|
remove_data: false,
|
||||||
ban,
|
ban,
|
||||||
|
@ -413,13 +413,13 @@ export async function removeComment(
|
||||||
return api.client.removeComment(form);
|
return api.client.removeComment(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getMentions(api: API): Promise<GetUserMentionsResponse> {
|
export async function getMentions(api: API): Promise<GetPersonMentionsResponse> {
|
||||||
let form: GetUserMentions = {
|
let form: GetPersonMentions = {
|
||||||
sort: SortType.New,
|
sort: SortType.New,
|
||||||
unread_only: false,
|
unread_only: false,
|
||||||
auth: api.auth,
|
auth: api.auth,
|
||||||
};
|
};
|
||||||
return api.client.getUserMentions(form);
|
return api.client.getPersonMentions(form);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function likeComment(
|
export async function likeComment(
|
||||||
|
@ -448,7 +448,6 @@ export async function createCommunity(
|
||||||
description,
|
description,
|
||||||
icon,
|
icon,
|
||||||
banner,
|
banner,
|
||||||
category_id: 1,
|
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
auth: api.auth,
|
auth: api.auth,
|
||||||
};
|
};
|
||||||
|
|
|
@ -8,7 +8,7 @@ import {
|
||||||
getSite,
|
getSite,
|
||||||
} from './shared';
|
} from './shared';
|
||||||
import {
|
import {
|
||||||
UserViewSafe,
|
PersonViewSafe,
|
||||||
SaveUserSettings,
|
SaveUserSettings,
|
||||||
SortType,
|
SortType,
|
||||||
ListingType,
|
ListingType,
|
||||||
|
@ -17,14 +17,14 @@ import {
|
||||||
let auth: string;
|
let auth: string;
|
||||||
let apShortname: string;
|
let apShortname: string;
|
||||||
|
|
||||||
function assertUserFederation(userOne: UserViewSafe, userTwo: UserViewSafe) {
|
function assertUserFederation(userOne: PersonViewSafe, userTwo: PersonViewSafe) {
|
||||||
expect(userOne.user.name).toBe(userTwo.user.name);
|
expect(userOne.person.name).toBe(userTwo.person.name);
|
||||||
expect(userOne.user.preferred_username).toBe(userTwo.user.preferred_username);
|
expect(userOne.person.preferred_username).toBe(userTwo.person.preferred_username);
|
||||||
expect(userOne.user.bio).toBe(userTwo.user.bio);
|
expect(userOne.person.bio).toBe(userTwo.person.bio);
|
||||||
expect(userOne.user.actor_id).toBe(userTwo.user.actor_id);
|
expect(userOne.person.actor_id).toBe(userTwo.person.actor_id);
|
||||||
expect(userOne.user.avatar).toBe(userTwo.user.avatar);
|
expect(userOne.person.avatar).toBe(userTwo.person.avatar);
|
||||||
expect(userOne.user.banner).toBe(userTwo.user.banner);
|
expect(userOne.person.banner).toBe(userTwo.person.banner);
|
||||||
expect(userOne.user.published).toBe(userTwo.user.published);
|
expect(userOne.person.published).toBe(userTwo.person.published);
|
||||||
}
|
}
|
||||||
|
|
||||||
test('Create user', async () => {
|
test('Create user', async () => {
|
||||||
|
@ -34,7 +34,7 @@ test('Create user', async () => {
|
||||||
|
|
||||||
let site = await getSite(alpha, auth);
|
let site = await getSite(alpha, auth);
|
||||||
expect(site.my_user).toBeDefined();
|
expect(site.my_user).toBeDefined();
|
||||||
apShortname = `@${site.my_user.name}@lemmy-alpha:8541`;
|
apShortname = `@${site.my_user.person.name}@lemmy-alpha:8541`;
|
||||||
});
|
});
|
||||||
|
|
||||||
test('Set some user settings, check that they are federated', async () => {
|
test('Set some user settings, check that they are federated', async () => {
|
||||||
|
|
|
@ -3233,10 +3233,10 @@ language-tags@^1.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
language-subtag-registry "~0.3.2"
|
language-subtag-registry "~0.3.2"
|
||||||
|
|
||||||
lemmy-js-client@0.9.1-rc.1:
|
lemmy-js-client@0.10.0-rc.4:
|
||||||
version "0.9.1-rc.1"
|
version "0.10.0-rc.4"
|
||||||
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.9.1-rc.1.tgz#afe3cb0d4852f849dd087a4756a3771bc920a907"
|
resolved "https://registry.yarnpkg.com/lemmy-js-client/-/lemmy-js-client-0.10.0-rc.4.tgz#ac6fe6940fc5f73260ddb166ce0ef3c0520901fc"
|
||||||
integrity sha512-aVvo4IeJvIPUvypipk4GnyLB6nVQVLfB0arYrMkVV4L7zrZ/0pGtpkMDLaOAj/KpA6O0u9eLmaou5RberZQolA==
|
integrity sha512-yJPnvGaWneOOwjKEqb4qXtQk+4DbRgO+hEzSin2GgUgnxluY43gemwiCPt6EnV+j4ueKoi0+QORVg2RuRC2PaQ==
|
||||||
|
|
||||||
leven@^3.1.0:
|
leven@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
http-signature-normalization-actix = { version = "0.4.1", default-features = false, features = ["sha-2"] }
|
||||||
|
|
|
@ -2,9 +2,9 @@ use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
check_downvotes_enabled,
|
check_downvotes_enabled,
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
|
get_local_user_view_from_jwt,
|
||||||
|
get_local_user_view_from_jwt_opt,
|
||||||
get_post,
|
get_post,
|
||||||
get_user_from_jwt,
|
|
||||||
get_user_from_jwt_opt,
|
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
Perform,
|
Perform,
|
||||||
};
|
};
|
||||||
|
@ -20,10 +20,14 @@ use lemmy_db_queries::{
|
||||||
Saveable,
|
Saveable,
|
||||||
SortType,
|
SortType,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{comment::*, comment_report::*, moderator::*};
|
use lemmy_db_schema::{
|
||||||
|
source::{comment::*, comment_report::*, moderator::*},
|
||||||
|
LocalUserId,
|
||||||
|
};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
comment_report_view::{CommentReportQueryBuilder, CommentReportView},
|
||||||
comment_view::{CommentQueryBuilder, CommentView},
|
comment_view::{CommentQueryBuilder, CommentView},
|
||||||
|
local_user_view::LocalUserView,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
utils::{remove_slurs, scrape_text_for_mentions},
|
utils::{remove_slurs, scrape_text_for_mentions},
|
||||||
|
@ -48,7 +52,7 @@ impl Perform for CreateComment {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &CreateComment = &self;
|
let data: &CreateComment = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let content_slurs_removed = remove_slurs(&data.content.to_owned());
|
let content_slurs_removed = remove_slurs(&data.content.to_owned());
|
||||||
|
|
||||||
|
@ -56,7 +60,7 @@ impl Perform for CreateComment {
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post = get_post(post_id, context.pool()).await?;
|
let post = get_post(post_id, context.pool()).await?;
|
||||||
|
|
||||||
check_community_ban(user.id, post.community_id, context.pool()).await?;
|
check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
|
||||||
|
|
||||||
// Check if post is locked, no new comments
|
// Check if post is locked, no new comments
|
||||||
if post.locked {
|
if post.locked {
|
||||||
|
@ -80,7 +84,7 @@ impl Perform for CreateComment {
|
||||||
content: content_slurs_removed,
|
content: content_slurs_removed,
|
||||||
parent_id: data.parent_id.to_owned(),
|
parent_id: data.parent_id.to_owned(),
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
creator_id: user.id,
|
creator_id: local_user_view.person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
read: None,
|
read: None,
|
||||||
|
@ -115,7 +119,9 @@ impl Perform for CreateComment {
|
||||||
Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()),
|
Err(_e) => return Err(ApiError::err("couldnt_create_comment").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
updated_comment.send_create(&user, context).await?;
|
updated_comment
|
||||||
|
.send_create(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Scan the comment for user mentions, add those rows
|
// Scan the comment for user mentions, add those rows
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
|
@ -123,7 +129,7 @@ impl Perform for CreateComment {
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment.clone(),
|
updated_comment.clone(),
|
||||||
&user,
|
local_user_view.person.clone(),
|
||||||
post,
|
post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
true,
|
true,
|
||||||
|
@ -134,7 +140,7 @@ impl Perform for CreateComment {
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id,
|
post_id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,17 +149,19 @@ impl Perform for CreateComment {
|
||||||
return Err(ApiError::err("couldnt_like_comment").into());
|
return Err(ApiError::err("couldnt_like_comment").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
updated_comment.send_like(&user, context).await?;
|
updated_comment
|
||||||
|
.send_like(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let mut comment_view = blocking(context.pool(), move |conn| {
|
let mut comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(&conn, inserted_comment.id, Some(user_id))
|
CommentView::read(&conn, inserted_comment.id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
// If its a comment to yourself, mark it as read
|
// If its a comment to yourself, mark it as read
|
||||||
let comment_id = comment_view.comment.id;
|
let comment_id = comment_view.comment.id;
|
||||||
if user.id == comment_view.get_recipient_id() {
|
if local_user_view.person.id == comment_view.get_recipient_id() {
|
||||||
match blocking(context.pool(), move |conn| {
|
match blocking(context.pool(), move |conn| {
|
||||||
Comment::update_read(conn, comment_id, true)
|
Comment::update_read(conn, comment_id, true)
|
||||||
})
|
})
|
||||||
|
@ -193,7 +201,7 @@ impl Perform for EditComment {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &EditComment = &self;
|
let data: &EditComment = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
|
@ -201,10 +209,15 @@ impl Perform for EditComment {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the creator can edit
|
// Verify that only the creator can edit
|
||||||
if user.id != orig_comment.creator.id {
|
if local_user_view.person.id != orig_comment.creator.id {
|
||||||
return Err(ApiError::err("no_comment_edit_allowed").into());
|
return Err(ApiError::err("no_comment_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -221,7 +234,9 @@ impl Perform for EditComment {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send the apub update
|
// Send the apub update
|
||||||
updated_comment.send_update(&user, context).await?;
|
updated_comment
|
||||||
|
.send_update(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Do the mentions / recipients
|
// Do the mentions / recipients
|
||||||
let updated_comment_content = updated_comment.content.to_owned();
|
let updated_comment_content = updated_comment.content.to_owned();
|
||||||
|
@ -229,7 +244,7 @@ impl Perform for EditComment {
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
local_user_view.person.clone(),
|
||||||
orig_comment.post,
|
orig_comment.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
|
@ -237,9 +252,9 @@ impl Perform for EditComment {
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -269,7 +284,7 @@ impl Perform for DeleteComment {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &DeleteComment = &self;
|
let data: &DeleteComment = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
|
@ -277,10 +292,15 @@ impl Perform for DeleteComment {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the creator can delete
|
// Verify that only the creator can delete
|
||||||
if user.id != orig_comment.creator.id {
|
if local_user_view.person.id != orig_comment.creator.id {
|
||||||
return Err(ApiError::err("no_comment_edit_allowed").into());
|
return Err(ApiError::err("no_comment_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,16 +317,20 @@ impl Perform for DeleteComment {
|
||||||
|
|
||||||
// Send the apub message
|
// Send the apub message
|
||||||
if deleted {
|
if deleted {
|
||||||
updated_comment.send_delete(&user, context).await?;
|
updated_comment
|
||||||
|
.send_delete(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
updated_comment.send_undo_delete(&user, context).await?;
|
updated_comment
|
||||||
|
.send_undo_delete(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refetch it
|
// Refetch it
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -316,7 +340,7 @@ impl Perform for DeleteComment {
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
local_user_view.person.clone(),
|
||||||
comment_view_2.post,
|
comment_view_2.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
|
@ -349,7 +373,7 @@ impl Perform for RemoveComment {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &RemoveComment = &self;
|
let data: &RemoveComment = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
|
@ -357,10 +381,20 @@ impl Perform for RemoveComment {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only a mod or admin can remove
|
// Verify that only a mod or admin can remove
|
||||||
is_mod_or_admin(context.pool(), user.id, orig_comment.community.id).await?;
|
is_mod_or_admin(
|
||||||
|
context.pool(),
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Do the remove
|
// Do the remove
|
||||||
let removed = data.removed;
|
let removed = data.removed;
|
||||||
|
@ -375,7 +409,7 @@ impl Perform for RemoveComment {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModRemoveCommentForm {
|
let form = ModRemoveCommentForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
comment_id: data.comment_id,
|
comment_id: data.comment_id,
|
||||||
removed: Some(removed),
|
removed: Some(removed),
|
||||||
reason: data.reason.to_owned(),
|
reason: data.reason.to_owned(),
|
||||||
|
@ -387,16 +421,20 @@ impl Perform for RemoveComment {
|
||||||
|
|
||||||
// Send the apub message
|
// Send the apub message
|
||||||
if removed {
|
if removed {
|
||||||
updated_comment.send_remove(&user, context).await?;
|
updated_comment
|
||||||
|
.send_remove(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
updated_comment.send_undo_remove(&user, context).await?;
|
updated_comment
|
||||||
|
.send_undo_remove(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refetch it
|
// Refetch it
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -407,7 +445,7 @@ impl Perform for RemoveComment {
|
||||||
let recipient_ids = send_local_notifs(
|
let recipient_ids = send_local_notifs(
|
||||||
mentions,
|
mentions,
|
||||||
updated_comment,
|
updated_comment,
|
||||||
&user,
|
local_user_view.person.clone(),
|
||||||
comment_view_2.post,
|
comment_view_2.post,
|
||||||
context.pool(),
|
context.pool(),
|
||||||
false,
|
false,
|
||||||
|
@ -440,7 +478,7 @@ impl Perform for MarkCommentAsRead {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &MarkCommentAsRead = &self;
|
let data: &MarkCommentAsRead = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let orig_comment = blocking(context.pool(), move |conn| {
|
let orig_comment = blocking(context.pool(), move |conn| {
|
||||||
|
@ -448,10 +486,15 @@ impl Perform for MarkCommentAsRead {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the recipient can mark as read
|
// Verify that only the recipient can mark as read
|
||||||
if user.id != orig_comment.get_recipient_id() {
|
if local_user_view.person.id != orig_comment.get_recipient_id() {
|
||||||
return Err(ApiError::err("no_comment_edit_allowed").into());
|
return Err(ApiError::err("no_comment_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,9 +511,9 @@ impl Perform for MarkCommentAsRead {
|
||||||
|
|
||||||
// Refetch it
|
// Refetch it
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -494,11 +537,11 @@ impl Perform for SaveComment {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &SaveComment = &self;
|
let data: &SaveComment = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let comment_saved_form = CommentSavedForm {
|
let comment_saved_form = CommentSavedForm {
|
||||||
comment_id: data.comment_id,
|
comment_id: data.comment_id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if data.save {
|
if data.save {
|
||||||
|
@ -514,9 +557,9 @@ impl Perform for SaveComment {
|
||||||
}
|
}
|
||||||
|
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -538,9 +581,9 @@ impl Perform for CreateCommentLike {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommentResponse, LemmyError> {
|
) -> Result<CommentResponse, LemmyError> {
|
||||||
let data: &CreateCommentLike = &self;
|
let data: &CreateCommentLike = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let mut recipient_ids = Vec::new();
|
let mut recipient_ids = Vec::<LocalUserId>::new();
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
// Don't do a downvote if site has downvotes disabled
|
||||||
check_downvotes_enabled(data.score, context.pool()).await?;
|
check_downvotes_enabled(data.score, context.pool()).await?;
|
||||||
|
@ -551,22 +594,34 @@ impl Perform for CreateCommentLike {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_comment.community.id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_comment.community.id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Add parent user to recipients
|
// Add parent user to recipients
|
||||||
recipient_ids.push(orig_comment.get_recipient_id());
|
let recipient_id = orig_comment.get_recipient_id();
|
||||||
|
if let Ok(local_recipient) = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await?
|
||||||
|
{
|
||||||
|
recipient_ids.push(local_recipient.local_user.id);
|
||||||
|
}
|
||||||
|
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id: data.comment_id,
|
comment_id: data.comment_id,
|
||||||
post_id: orig_comment.post.id,
|
post_id: orig_comment.post.id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
score: data.score,
|
score: data.score,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove any likes first
|
// Remove any likes first
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
CommentLike::remove(conn, user_id, comment_id)
|
CommentLike::remove(conn, person_id, comment_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -581,19 +636,23 @@ impl Perform for CreateCommentLike {
|
||||||
}
|
}
|
||||||
|
|
||||||
if like_form.score == 1 {
|
if like_form.score == 1 {
|
||||||
comment.send_like(&user, context).await?;
|
comment.send_like(&local_user_view.person, context).await?;
|
||||||
} else if like_form.score == -1 {
|
} else if like_form.score == -1 {
|
||||||
comment.send_dislike(&user, context).await?;
|
comment
|
||||||
|
.send_dislike(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
comment.send_undo_like(&user, context).await?;
|
comment
|
||||||
|
.send_undo_like(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Have to refetch the comment to get the current state
|
// Have to refetch the comment to get the current state
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let liked_comment = blocking(context.pool(), move |conn| {
|
let liked_comment = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(conn, comment_id, Some(user_id))
|
CommentView::read(conn, comment_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -623,8 +682,8 @@ impl Perform for GetComments {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetCommentsResponse, LemmyError> {
|
) -> Result<GetCommentsResponse, LemmyError> {
|
||||||
let data: &GetComments = &self;
|
let data: &GetComments = &self;
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let user_id = user.map(|u| u.id);
|
let person_id = local_user_view.map(|u| u.person.id);
|
||||||
|
|
||||||
let type_ = ListingType::from_str(&data.type_)?;
|
let type_ = ListingType::from_str(&data.type_)?;
|
||||||
let sort = SortType::from_str(&data.sort)?;
|
let sort = SortType::from_str(&data.sort)?;
|
||||||
|
@ -639,7 +698,7 @@ impl Perform for GetComments {
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.community_name(community_name)
|
.community_name(community_name)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -665,7 +724,7 @@ impl Perform for CreateCommentReport {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CreateCommentReportResponse, LemmyError> {
|
) -> Result<CreateCommentReportResponse, LemmyError> {
|
||||||
let data: &CreateCommentReport = &self;
|
let data: &CreateCommentReport = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// check size of report and check for whitespace
|
// check size of report and check for whitespace
|
||||||
let reason = data.reason.trim();
|
let reason = data.reason.trim();
|
||||||
|
@ -676,17 +735,17 @@ impl Perform for CreateCommentReport {
|
||||||
return Err(ApiError::err("report_too_long").into());
|
return Err(ApiError::err("report_too_long").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let comment_id = data.comment_id;
|
let comment_id = data.comment_id;
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
CommentView::read(&conn, comment_id, None)
|
CommentView::read(&conn, comment_id, None)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user_id, comment_view.community.id, context.pool()).await?;
|
check_community_ban(person_id, comment_view.community.id, context.pool()).await?;
|
||||||
|
|
||||||
let report_form = CommentReportForm {
|
let report_form = CommentReportForm {
|
||||||
creator_id: user_id,
|
creator_id: person_id,
|
||||||
comment_id,
|
comment_id,
|
||||||
original_comment_text: comment_view.comment.content,
|
original_comment_text: comment_view.comment.content,
|
||||||
reason: data.reason.to_owned(),
|
reason: data.reason.to_owned(),
|
||||||
|
@ -706,7 +765,7 @@ impl Perform for CreateCommentReport {
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::CreateCommentReport,
|
op: UserOperation::CreateCommentReport,
|
||||||
response: res.clone(),
|
response: res.clone(),
|
||||||
recipient_id: user.id,
|
local_recipient_id: local_user_view.local_user.id,
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -732,7 +791,7 @@ impl Perform for ResolveCommentReport {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<ResolveCommentReportResponse, LemmyError> {
|
) -> Result<ResolveCommentReportResponse, LemmyError> {
|
||||||
let data: &ResolveCommentReport = &self;
|
let data: &ResolveCommentReport = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let report_id = data.report_id;
|
let report_id = data.report_id;
|
||||||
let report = blocking(context.pool(), move |conn| {
|
let report = blocking(context.pool(), move |conn| {
|
||||||
|
@ -740,15 +799,15 @@ impl Perform for ResolveCommentReport {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
is_mod_or_admin(context.pool(), user_id, report.community.id).await?;
|
is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
|
||||||
|
|
||||||
let resolved = data.resolved;
|
let resolved = data.resolved;
|
||||||
let resolve_fun = move |conn: &'_ _| {
|
let resolve_fun = move |conn: &'_ _| {
|
||||||
if resolved {
|
if resolved {
|
||||||
CommentReport::resolve(conn, report_id, user_id)
|
CommentReport::resolve(conn, report_id, person_id)
|
||||||
} else {
|
} else {
|
||||||
CommentReport::unresolve(conn, report_id, user_id)
|
CommentReport::unresolve(conn, report_id, person_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -785,12 +844,12 @@ impl Perform for ListCommentReports {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<ListCommentReportsResponse, LemmyError> {
|
) -> Result<ListCommentReportsResponse, LemmyError> {
|
||||||
let data: &ListCommentReports = &self;
|
let data: &ListCommentReports = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_id = data.community;
|
let community_id = data.community;
|
||||||
let community_ids =
|
let community_ids =
|
||||||
collect_moderated_communities(user_id, community_id, context.pool()).await?;
|
collect_moderated_communities(person_id, community_id, context.pool()).await?;
|
||||||
|
|
||||||
let page = data.page;
|
let page = data.page;
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
|
@ -808,7 +867,7 @@ impl Perform for ListCommentReports {
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::ListCommentReports,
|
op: UserOperation::ListCommentReports,
|
||||||
response: res.clone(),
|
response: res.clone(),
|
||||||
recipient_id: user.id,
|
local_recipient_id: local_user_view.local_user.id,
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
check_optional_url,
|
get_local_user_view_from_jwt,
|
||||||
get_user_from_jwt,
|
get_local_user_view_from_jwt_opt,
|
||||||
get_user_from_jwt_opt,
|
|
||||||
is_admin,
|
is_admin,
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
Perform,
|
Perform,
|
||||||
|
@ -19,7 +18,7 @@ use lemmy_apub::{
|
||||||
EndpointType,
|
EndpointType,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_queries::{
|
||||||
diesel_option_overwrite,
|
diesel_option_overwrite_to_url,
|
||||||
source::{
|
source::{
|
||||||
comment::Comment_,
|
comment::Comment_,
|
||||||
community::{CommunityModerator_, Community_},
|
community::{CommunityModerator_, Community_},
|
||||||
|
@ -36,13 +35,14 @@ use lemmy_db_queries::{
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::{comment::Comment, community::*, moderator::*, post::Post, site::*},
|
source::{comment::Comment, community::*, moderator::*, post::Post, site::*},
|
||||||
|
PersonId,
|
||||||
};
|
};
|
||||||
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
use lemmy_db_views::comment_view::CommentQueryBuilder;
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_follower_view::CommunityFollowerView,
|
community_follower_view::CommunityFollowerView,
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
community_view::{CommunityQueryBuilder, CommunityView},
|
community_view::{CommunityQueryBuilder, CommunityView},
|
||||||
user_view::UserViewSafe,
|
person_view::PersonViewSafe,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
apub::generate_actor_keypair,
|
apub::generate_actor_keypair,
|
||||||
|
@ -69,8 +69,8 @@ impl Perform for GetCommunity {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetCommunityResponse, LemmyError> {
|
) -> Result<GetCommunityResponse, LemmyError> {
|
||||||
let data: &GetCommunity = &self;
|
let data: &GetCommunity = &self;
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let user_id = user.map(|u| u.id);
|
let person_id = local_user_view.map(|u| u.person.id);
|
||||||
|
|
||||||
let community_id = match data.id {
|
let community_id = match data.id {
|
||||||
Some(id) => id,
|
Some(id) => id,
|
||||||
|
@ -89,7 +89,7 @@ impl Perform for GetCommunity {
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_view = match blocking(context.pool(), move |conn| {
|
let community_view = match blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, user_id)
|
CommunityView::read(conn, community_id, person_id)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -133,7 +133,7 @@ impl Perform for CreateCommunity {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommunityResponse, LemmyError> {
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
let data: &CreateCommunity = &self;
|
let data: &CreateCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.name)?;
|
check_slurs(&data.name)?;
|
||||||
check_slurs(&data.title)?;
|
check_slurs(&data.title)?;
|
||||||
|
@ -155,11 +155,8 @@ impl Perform for CreateCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check to make sure the icon and banners are urls
|
// Check to make sure the icon and banners are urls
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
check_optional_url(&icon)?;
|
|
||||||
check_optional_url(&banner)?;
|
|
||||||
|
|
||||||
// When you create a community, make sure the user becomes a moderator and a follower
|
// When you create a community, make sure the user becomes a moderator and a follower
|
||||||
let keypair = generate_actor_keypair()?;
|
let keypair = generate_actor_keypair()?;
|
||||||
|
@ -170,7 +167,7 @@ impl Perform for CreateCommunity {
|
||||||
description: data.description.to_owned(),
|
description: data.description.to_owned(),
|
||||||
icon,
|
icon,
|
||||||
banner,
|
banner,
|
||||||
creator_id: user.id,
|
creator_id: local_user_view.person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
nsfw: data.nsfw,
|
nsfw: data.nsfw,
|
||||||
|
@ -198,7 +195,7 @@ impl Perform for CreateCommunity {
|
||||||
// The community creator becomes a moderator
|
// The community creator becomes a moderator
|
||||||
let community_moderator_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||||
|
@ -209,7 +206,7 @@ impl Perform for CreateCommunity {
|
||||||
// Follow your own community
|
// Follow your own community
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -218,9 +215,9 @@ impl Perform for CreateCommunity {
|
||||||
return Err(ApiError::err("community_follower_already_exists").into());
|
return Err(ApiError::err("community_follower_already_exists").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_view = blocking(context.pool(), move |conn| {
|
let community_view = blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, inserted_community.id, Some(user_id))
|
CommunityView::read(conn, inserted_community.id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -238,19 +235,19 @@ impl Perform for EditCommunity {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommunityResponse, LemmyError> {
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
let data: &EditCommunity = &self;
|
let data: &EditCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.title)?;
|
check_slurs(&data.title)?;
|
||||||
check_slurs_opt(&data.description)?;
|
check_slurs_opt(&data.description)?;
|
||||||
|
|
||||||
// Verify its a mod (only mods can edit it)
|
// Verify its a mod (only mods can edit it)
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let mods: Vec<i32> = blocking(context.pool(), move |conn| {
|
let mods: Vec<PersonId> = blocking(context.pool(), move |conn| {
|
||||||
CommunityModeratorView::for_community(conn, community_id)
|
CommunityModeratorView::for_community(conn, community_id)
|
||||||
.map(|v| v.into_iter().map(|m| m.moderator.id).collect())
|
.map(|v| v.into_iter().map(|m| m.moderator.id).collect())
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
if !mods.contains(&user.id) {
|
if !mods.contains(&local_user_view.person.id) {
|
||||||
return Err(ApiError::err("not_a_moderator").into());
|
return Err(ApiError::err("not_a_moderator").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,11 +257,8 @@ impl Perform for EditCommunity {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
check_optional_url(&icon)?;
|
|
||||||
check_optional_url(&banner)?;
|
|
||||||
|
|
||||||
let community_form = CommunityForm {
|
let community_form = CommunityForm {
|
||||||
name: read_community.name,
|
name: read_community.name,
|
||||||
|
@ -302,9 +296,9 @@ impl Perform for EditCommunity {
|
||||||
// process for communities and users
|
// process for communities and users
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_view = blocking(context.pool(), move |conn| {
|
let community_view = blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, Some(user_id))
|
CommunityView::read(conn, community_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -326,7 +320,7 @@ impl Perform for DeleteCommunity {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommunityResponse, LemmyError> {
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
let data: &DeleteCommunity = &self;
|
let data: &DeleteCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Verify its the creator (only a creator can delete the community)
|
// Verify its the creator (only a creator can delete the community)
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
|
@ -334,7 +328,7 @@ impl Perform for DeleteCommunity {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
if read_community.creator_id != user.id {
|
if read_community.creator_id != local_user_view.person.id {
|
||||||
return Err(ApiError::err("no_community_edit_allowed").into());
|
return Err(ApiError::err("no_community_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,9 +352,9 @@ impl Perform for DeleteCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_view = blocking(context.pool(), move |conn| {
|
let community_view = blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, Some(user_id))
|
CommunityView::read(conn, community_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -382,10 +376,10 @@ impl Perform for RemoveCommunity {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommunityResponse, LemmyError> {
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
let data: &RemoveCommunity = &self;
|
let data: &RemoveCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Verify its an admin (only an admin can remove a community)
|
// Verify its an admin (only an admin can remove a community)
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
// Do the remove
|
// Do the remove
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
|
@ -405,7 +399,7 @@ impl Perform for RemoveCommunity {
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let form = ModRemoveCommunityForm {
|
let form = ModRemoveCommunityForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
removed: Some(removed),
|
removed: Some(removed),
|
||||||
reason: data.reason.to_owned(),
|
reason: data.reason.to_owned(),
|
||||||
|
@ -424,9 +418,9 @@ impl Perform for RemoveCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_view = blocking(context.pool(), move |conn| {
|
let community_view = blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, Some(user_id))
|
CommunityView::read(conn, community_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -448,15 +442,16 @@ impl Perform for ListCommunities {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<ListCommunitiesResponse, LemmyError> {
|
) -> Result<ListCommunitiesResponse, LemmyError> {
|
||||||
let data: &ListCommunities = &self;
|
let data: &ListCommunities = &self;
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = match &user {
|
let person_id = match &local_user_view {
|
||||||
Some(user) => Some(user.id),
|
Some(uv) => Some(uv.person.id),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let show_nsfw = match &user {
|
// Don't show NSFW by default
|
||||||
Some(user) => user.show_nsfw,
|
let show_nsfw = match &local_user_view {
|
||||||
|
Some(uv) => uv.local_user.show_nsfw,
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -470,7 +465,7 @@ impl Perform for ListCommunities {
|
||||||
.listing_type(&type_)
|
.listing_type(&type_)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.show_nsfw(show_nsfw)
|
.show_nsfw(show_nsfw)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -492,7 +487,7 @@ impl Perform for FollowCommunity {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CommunityResponse, LemmyError> {
|
) -> Result<CommunityResponse, LemmyError> {
|
||||||
let data: &FollowCommunity = &self;
|
let data: &FollowCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
|
@ -501,13 +496,13 @@ impl Perform for FollowCommunity {
|
||||||
.await??;
|
.await??;
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
if community.local {
|
if community.local {
|
||||||
if data.follow {
|
if data.follow {
|
||||||
check_community_ban(user.id, community_id, context.pool()).await?;
|
check_community_ban(local_user_view.person.id, community_id, context.pool()).await?;
|
||||||
|
|
||||||
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
|
let follow = move |conn: &'_ _| CommunityFollower::follow(conn, &community_follower_form);
|
||||||
if blocking(context.pool(), follow).await?.is_err() {
|
if blocking(context.pool(), follow).await?.is_err() {
|
||||||
|
@ -523,9 +518,15 @@ impl Perform for FollowCommunity {
|
||||||
} else if data.follow {
|
} else if data.follow {
|
||||||
// Dont actually add to the community followers here, because you need
|
// Dont actually add to the community followers here, because you need
|
||||||
// to wait for the accept
|
// to wait for the accept
|
||||||
user.send_follow(&community.actor_id(), context).await?;
|
local_user_view
|
||||||
|
.person
|
||||||
|
.send_follow(&community.actor_id(), context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
user.send_unfollow(&community.actor_id(), context).await?;
|
local_user_view
|
||||||
|
.person
|
||||||
|
.send_unfollow(&community.actor_id(), context)
|
||||||
|
.await?;
|
||||||
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
let unfollow = move |conn: &'_ _| CommunityFollower::unfollow(conn, &community_follower_form);
|
||||||
if blocking(context.pool(), unfollow).await?.is_err() {
|
if blocking(context.pool(), unfollow).await?.is_err() {
|
||||||
return Err(ApiError::err("community_follower_already_exists").into());
|
return Err(ApiError::err("community_follower_already_exists").into());
|
||||||
|
@ -533,9 +534,9 @@ impl Perform for FollowCommunity {
|
||||||
}
|
}
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let mut community_view = blocking(context.pool(), move |conn| {
|
let mut community_view = blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, Some(user_id))
|
CommunityView::read(conn, community_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -560,11 +561,11 @@ impl Perform for GetFollowedCommunities {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetFollowedCommunitiesResponse, LemmyError> {
|
) -> Result<GetFollowedCommunitiesResponse, LemmyError> {
|
||||||
let data: &GetFollowedCommunities = &self;
|
let data: &GetFollowedCommunities = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let communities = match blocking(context.pool(), move |conn| {
|
let communities = match blocking(context.pool(), move |conn| {
|
||||||
CommunityFollowerView::for_user(conn, user_id)
|
CommunityFollowerView::for_person(conn, person_id)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -587,21 +588,21 @@ impl Perform for BanFromCommunity {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<BanFromCommunityResponse, LemmyError> {
|
) -> Result<BanFromCommunityResponse, LemmyError> {
|
||||||
let data: &BanFromCommunity = &self;
|
let data: &BanFromCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let banned_user_id = data.user_id;
|
let banned_person_id = data.person_id;
|
||||||
|
|
||||||
// Verify that only mods or admins can ban
|
// Verify that only mods or admins can ban
|
||||||
is_mod_or_admin(context.pool(), user.id, community_id).await?;
|
is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
|
||||||
|
|
||||||
let community_user_ban_form = CommunityUserBanForm {
|
let community_user_ban_form = CommunityPersonBanForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
user_id: data.user_id,
|
person_id: data.person_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if data.ban {
|
if data.ban {
|
||||||
let ban = move |conn: &'_ _| CommunityUserBan::ban(conn, &community_user_ban_form);
|
let ban = move |conn: &'_ _| CommunityPersonBan::ban(conn, &community_user_ban_form);
|
||||||
if blocking(context.pool(), ban).await?.is_err() {
|
if blocking(context.pool(), ban).await?.is_err() {
|
||||||
return Err(ApiError::err("community_user_already_banned").into());
|
return Err(ApiError::err("community_user_already_banned").into());
|
||||||
}
|
}
|
||||||
|
@ -609,7 +610,7 @@ impl Perform for BanFromCommunity {
|
||||||
// Also unsubscribe them from the community, if they are subscribed
|
// Also unsubscribe them from the community, if they are subscribed
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
user_id: banned_user_id,
|
person_id: banned_person_id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
|
@ -618,7 +619,7 @@ impl Perform for BanFromCommunity {
|
||||||
.await?
|
.await?
|
||||||
.ok();
|
.ok();
|
||||||
} else {
|
} else {
|
||||||
let unban = move |conn: &'_ _| CommunityUserBan::unban(conn, &community_user_ban_form);
|
let unban = move |conn: &'_ _| CommunityPersonBan::unban(conn, &community_user_ban_form);
|
||||||
if blocking(context.pool(), unban).await?.is_err() {
|
if blocking(context.pool(), unban).await?.is_err() {
|
||||||
return Err(ApiError::err("community_user_already_banned").into());
|
return Err(ApiError::err("community_user_already_banned").into());
|
||||||
}
|
}
|
||||||
|
@ -628,7 +629,7 @@ impl Perform for BanFromCommunity {
|
||||||
if data.remove_data {
|
if data.remove_data {
|
||||||
// Posts
|
// Posts
|
||||||
blocking(context.pool(), move |conn: &'_ _| {
|
blocking(context.pool(), move |conn: &'_ _| {
|
||||||
Post::update_removed_for_creator(conn, banned_user_id, Some(community_id), true)
|
Post::update_removed_for_creator(conn, banned_person_id, Some(community_id), true)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -636,7 +637,7 @@ impl Perform for BanFromCommunity {
|
||||||
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
|
// TODO Diesel doesn't allow updates with joins, so this has to be a loop
|
||||||
let comments = blocking(context.pool(), move |conn| {
|
let comments = blocking(context.pool(), move |conn| {
|
||||||
CommentQueryBuilder::create(conn)
|
CommentQueryBuilder::create(conn)
|
||||||
.creator_id(banned_user_id)
|
.creator_id(banned_person_id)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.limit(std::i64::MAX)
|
.limit(std::i64::MAX)
|
||||||
.list()
|
.list()
|
||||||
|
@ -660,8 +661,8 @@ impl Perform for BanFromCommunity {
|
||||||
};
|
};
|
||||||
|
|
||||||
let form = ModBanFromCommunityForm {
|
let form = ModBanFromCommunityForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_user_id: data.user_id,
|
other_person_id: data.person_id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
reason: data.reason.to_owned(),
|
reason: data.reason.to_owned(),
|
||||||
banned: Some(data.ban),
|
banned: Some(data.ban),
|
||||||
|
@ -672,14 +673,14 @@ impl Perform for BanFromCommunity {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let user_id = data.user_id;
|
let person_id = data.person_id;
|
||||||
let user_view = blocking(context.pool(), move |conn| {
|
let person_view = blocking(context.pool(), move |conn| {
|
||||||
UserViewSafe::read(conn, user_id)
|
PersonViewSafe::read(conn, person_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let res = BanFromCommunityResponse {
|
let res = BanFromCommunityResponse {
|
||||||
user_view,
|
person_view,
|
||||||
banned: data.ban,
|
banned: data.ban,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -704,17 +705,17 @@ impl Perform for AddModToCommunity {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<AddModToCommunityResponse, LemmyError> {
|
) -> Result<AddModToCommunityResponse, LemmyError> {
|
||||||
let data: &AddModToCommunity = &self;
|
let data: &AddModToCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let community_moderator_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
user_id: data.user_id,
|
person_id: data.person_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
|
|
||||||
// Verify that only mods or admins can add mod
|
// Verify that only mods or admins can add mod
|
||||||
is_mod_or_admin(context.pool(), user.id, community_id).await?;
|
is_mod_or_admin(context.pool(), local_user_view.person.id, community_id).await?;
|
||||||
|
|
||||||
if data.added {
|
if data.added {
|
||||||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||||
|
@ -730,8 +731,8 @@ impl Perform for AddModToCommunity {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModAddCommunityForm {
|
let form = ModAddCommunityForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_user_id: data.user_id,
|
other_person_id: data.person_id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
removed: Some(!data.added),
|
removed: Some(!data.added),
|
||||||
};
|
};
|
||||||
|
@ -769,7 +770,7 @@ impl Perform for TransferCommunity {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetCommunityResponse, LemmyError> {
|
) -> Result<GetCommunityResponse, LemmyError> {
|
||||||
let data: &TransferCommunity = &self;
|
let data: &TransferCommunity = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let read_community = blocking(context.pool(), move |conn| {
|
let read_community = blocking(context.pool(), move |conn| {
|
||||||
|
@ -782,25 +783,28 @@ impl Perform for TransferCommunity {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
|
||||||
|
|
||||||
// Making sure the creator, if an admin, is at the top
|
// Making sure the creator, if an admin, is at the top
|
||||||
let creator_index = admins
|
let creator_index = admins
|
||||||
.iter()
|
.iter()
|
||||||
.position(|r| r.user.id == site_creator_id)
|
.position(|r| r.person.id == site_creator_id)
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let creator_user = admins.remove(creator_index);
|
let creator_person = admins.remove(creator_index);
|
||||||
admins.insert(0, creator_user);
|
admins.insert(0, creator_person);
|
||||||
|
|
||||||
// Make sure user is the creator, or an admin
|
// Make sure user is the creator, or an admin
|
||||||
if user.id != read_community.creator_id
|
if local_user_view.person.id != read_community.creator_id
|
||||||
&& !admins.iter().map(|a| a.user.id).any(|x| x == user.id)
|
&& !admins
|
||||||
|
.iter()
|
||||||
|
.map(|a| a.person.id)
|
||||||
|
.any(|x| x == local_user_view.person.id)
|
||||||
{
|
{
|
||||||
return Err(ApiError::err("not_an_admin").into());
|
return Err(ApiError::err("not_an_admin").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let new_creator = data.user_id;
|
let new_creator = data.person_id;
|
||||||
let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator);
|
let update = move |conn: &'_ _| Community::update_creator(conn, community_id, new_creator);
|
||||||
if blocking(context.pool(), update).await?.is_err() {
|
if blocking(context.pool(), update).await?.is_err() {
|
||||||
return Err(ApiError::err("couldnt_update_community").into());
|
return Err(ApiError::err("couldnt_update_community").into());
|
||||||
|
@ -814,10 +818,10 @@ impl Perform for TransferCommunity {
|
||||||
.await??;
|
.await??;
|
||||||
let creator_index = community_mods
|
let creator_index = community_mods
|
||||||
.iter()
|
.iter()
|
||||||
.position(|r| r.moderator.id == data.user_id)
|
.position(|r| r.moderator.id == data.person_id)
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let creator_user = community_mods.remove(creator_index);
|
let creator_person = community_mods.remove(creator_index);
|
||||||
community_mods.insert(0, creator_user);
|
community_mods.insert(0, creator_person);
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
|
@ -829,7 +833,7 @@ impl Perform for TransferCommunity {
|
||||||
for cmod in &community_mods {
|
for cmod in &community_mods {
|
||||||
let community_moderator_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id: cmod.community.id,
|
community_id: cmod.community.id,
|
||||||
user_id: cmod.moderator.id,
|
person_id: cmod.moderator.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
let join = move |conn: &'_ _| CommunityModerator::join(conn, &community_moderator_form);
|
||||||
|
@ -840,8 +844,8 @@ impl Perform for TransferCommunity {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModAddCommunityForm {
|
let form = ModAddCommunityForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_user_id: data.user_id,
|
other_person_id: data.person_id,
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
removed: Some(false),
|
removed: Some(false),
|
||||||
};
|
};
|
||||||
|
@ -851,9 +855,9 @@ impl Perform for TransferCommunity {
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_view = match blocking(context.pool(), move |conn| {
|
let community_view = match blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, Some(user_id))
|
CommunityView::read(conn, community_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -886,7 +890,7 @@ fn send_community_websocket(
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
op: UserOperation,
|
op: UserOperation,
|
||||||
) {
|
) {
|
||||||
// Strip out the user id and subscribed when sending to others
|
// Strip out the person id and subscribed when sending to others
|
||||||
let mut res_sent = res.clone();
|
let mut res_sent = res.clone();
|
||||||
res_sent.community_view.subscribed = false;
|
res_sent.community_view.subscribed = false;
|
||||||
|
|
||||||
|
|
|
@ -3,28 +3,33 @@ use lemmy_api_structs::{
|
||||||
blocking,
|
blocking,
|
||||||
comment::*,
|
comment::*,
|
||||||
community::*,
|
community::*,
|
||||||
|
person::*,
|
||||||
post::*,
|
post::*,
|
||||||
site::*,
|
site::*,
|
||||||
user::*,
|
|
||||||
websocket::*,
|
websocket::*,
|
||||||
};
|
};
|
||||||
use lemmy_db_queries::{
|
use lemmy_db_queries::{
|
||||||
source::{
|
source::{
|
||||||
community::{CommunityModerator_, Community_},
|
community::{CommunityModerator_, Community_},
|
||||||
site::Site_,
|
site::Site_,
|
||||||
user::UserSafeSettings_,
|
|
||||||
},
|
},
|
||||||
Crud,
|
Crud,
|
||||||
DbPool,
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
community::{Community, CommunityModerator},
|
source::{
|
||||||
post::Post,
|
community::{Community, CommunityModerator},
|
||||||
site::Site,
|
post::Post,
|
||||||
user::{UserSafeSettings, User_},
|
site::Site,
|
||||||
|
},
|
||||||
|
CommunityId,
|
||||||
|
LocalUserId,
|
||||||
|
PersonId,
|
||||||
|
PostId,
|
||||||
};
|
};
|
||||||
|
use lemmy_db_views::local_user_view::{LocalUserSettingsView, LocalUserView};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_user_ban_view::CommunityUserBanView,
|
community_person_ban_view::CommunityPersonBanView,
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
|
@ -36,15 +41,15 @@ use lemmy_utils::{
|
||||||
};
|
};
|
||||||
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
|
use lemmy_websocket::{serialize_websocket_message, LemmyContext, UserOperation};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use std::process::Command;
|
use std::{env, process::Command};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod local_user;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod routes;
|
pub mod routes;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod user;
|
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
@ -60,11 +65,11 @@ pub trait Perform {
|
||||||
|
|
||||||
pub(crate) async fn is_mod_or_admin(
|
pub(crate) async fn is_mod_or_admin(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
user_id: i32,
|
person_id: PersonId,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let is_mod_or_admin = blocking(pool, move |conn| {
|
let is_mod_or_admin = blocking(pool, move |conn| {
|
||||||
CommunityView::is_mod_or_admin(conn, user_id, community_id)
|
CommunityView::is_mod_or_admin(conn, person_id, community_id)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if !is_mod_or_admin {
|
if !is_mod_or_admin {
|
||||||
|
@ -72,78 +77,107 @@ pub(crate) async fn is_mod_or_admin(
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
pub async fn is_admin(pool: &DbPool, user_id: i32) -> Result<(), LemmyError> {
|
|
||||||
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
pub fn is_admin(local_user_view: &LocalUserView) -> Result<(), LemmyError> {
|
||||||
if !user.admin {
|
if !local_user_view.local_user.admin {
|
||||||
return Err(ApiError::err("not_an_admin").into());
|
return Err(ApiError::err("not_an_admin").into());
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_post(post_id: i32, pool: &DbPool) -> Result<Post, LemmyError> {
|
pub(crate) async fn get_post(post_id: PostId, pool: &DbPool) -> Result<Post, LemmyError> {
|
||||||
match blocking(pool, move |conn| Post::read(conn, post_id)).await? {
|
match blocking(pool, move |conn| Post::read(conn, post_id)).await? {
|
||||||
Ok(post) => Ok(post),
|
Ok(post) => Ok(post),
|
||||||
Err(_e) => Err(ApiError::err("couldnt_find_post").into()),
|
Err(_e) => Err(ApiError::err("couldnt_find_post").into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_user_from_jwt(jwt: &str, pool: &DbPool) -> Result<User_, LemmyError> {
|
pub(crate) async fn get_local_user_view_from_jwt(
|
||||||
|
jwt: &str,
|
||||||
|
pool: &DbPool,
|
||||||
|
) -> Result<LocalUserView, LemmyError> {
|
||||||
let claims = match Claims::decode(&jwt) {
|
let claims = match Claims::decode(&jwt) {
|
||||||
Ok(claims) => claims.claims,
|
Ok(claims) => claims.claims,
|
||||||
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
|
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
let user_id = claims.id;
|
let local_user_id = LocalUserId(claims.sub);
|
||||||
let user = blocking(pool, move |conn| User_::read(conn, user_id)).await??;
|
let local_user_view =
|
||||||
|
blocking(pool, move |conn| LocalUserView::read(conn, local_user_id)).await??;
|
||||||
// Check for a site ban
|
// Check for a site ban
|
||||||
if user.banned {
|
if local_user_view.person.banned {
|
||||||
return Err(ApiError::err("site_ban").into());
|
return Err(ApiError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
Ok(user)
|
|
||||||
|
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
|
||||||
|
|
||||||
|
Ok(local_user_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_user_from_jwt_opt(
|
/// Checks if user's token was issued before user's password reset.
|
||||||
|
pub(crate) fn check_validator_time(
|
||||||
|
validator_time: &chrono::NaiveDateTime,
|
||||||
|
claims: &Claims,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
|
let user_validation_time = validator_time.timestamp();
|
||||||
|
if user_validation_time > claims.iat {
|
||||||
|
Err(ApiError::err("not_logged_in").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn get_local_user_view_from_jwt_opt(
|
||||||
jwt: &Option<String>,
|
jwt: &Option<String>,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<Option<User_>, LemmyError> {
|
) -> Result<Option<LocalUserView>, LemmyError> {
|
||||||
match jwt {
|
match jwt {
|
||||||
Some(jwt) => Ok(Some(get_user_from_jwt(jwt, pool).await?)),
|
Some(jwt) => Ok(Some(get_local_user_view_from_jwt(jwt, pool).await?)),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_user_safe_settings_from_jwt(
|
pub(crate) async fn get_local_user_settings_view_from_jwt(
|
||||||
jwt: &str,
|
jwt: &str,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<UserSafeSettings, LemmyError> {
|
) -> Result<LocalUserSettingsView, LemmyError> {
|
||||||
let claims = match Claims::decode(&jwt) {
|
let claims = match Claims::decode(&jwt) {
|
||||||
Ok(claims) => claims.claims,
|
Ok(claims) => claims.claims,
|
||||||
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
|
Err(_e) => return Err(ApiError::err("not_logged_in").into()),
|
||||||
};
|
};
|
||||||
let user_id = claims.id;
|
let local_user_id = LocalUserId(claims.sub);
|
||||||
let user = blocking(pool, move |conn| UserSafeSettings::read(conn, user_id)).await??;
|
let local_user_view = blocking(pool, move |conn| {
|
||||||
|
LocalUserSettingsView::read(conn, local_user_id)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
// Check for a site ban
|
// Check for a site ban
|
||||||
if user.banned {
|
if local_user_view.person.banned {
|
||||||
return Err(ApiError::err("site_ban").into());
|
return Err(ApiError::err("site_ban").into());
|
||||||
}
|
}
|
||||||
Ok(user)
|
|
||||||
|
check_validator_time(&local_user_view.local_user.validator_time, &claims)?;
|
||||||
|
|
||||||
|
Ok(local_user_view)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn get_user_safe_settings_from_jwt_opt(
|
pub(crate) async fn get_local_user_settings_view_from_jwt_opt(
|
||||||
jwt: &Option<String>,
|
jwt: &Option<String>,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<Option<UserSafeSettings>, LemmyError> {
|
) -> Result<Option<LocalUserSettingsView>, LemmyError> {
|
||||||
match jwt {
|
match jwt {
|
||||||
Some(jwt) => Ok(Some(get_user_safe_settings_from_jwt(jwt, pool).await?)),
|
Some(jwt) => Ok(Some(
|
||||||
|
get_local_user_settings_view_from_jwt(jwt, pool).await?,
|
||||||
|
)),
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn check_community_ban(
|
pub(crate) async fn check_community_ban(
|
||||||
user_id: i32,
|
person_id: PersonId,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||||
if blocking(pool, is_banned).await? {
|
if blocking(pool, is_banned).await? {
|
||||||
Err(ApiError::err("community_ban").into())
|
Err(ApiError::err("community_ban").into())
|
||||||
} else {
|
} else {
|
||||||
|
@ -165,36 +199,27 @@ pub(crate) async fn check_downvotes_enabled(score: i16, pool: &DbPool) -> Result
|
||||||
/// or if a community_id is supplied validates the user is a moderator
|
/// or if a community_id is supplied validates the user is a moderator
|
||||||
/// of that community and returns the community id in a vec
|
/// of that community and returns the community id in a vec
|
||||||
///
|
///
|
||||||
/// * `user_id` - the user id of the moderator
|
/// * `person_id` - the person id of the moderator
|
||||||
/// * `community_id` - optional community id to check for moderator privileges
|
/// * `community_id` - optional community id to check for moderator privileges
|
||||||
/// * `pool` - the diesel db pool
|
/// * `pool` - the diesel db pool
|
||||||
pub(crate) async fn collect_moderated_communities(
|
pub(crate) async fn collect_moderated_communities(
|
||||||
user_id: i32,
|
person_id: PersonId,
|
||||||
community_id: Option<i32>,
|
community_id: Option<CommunityId>,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<Vec<i32>, LemmyError> {
|
) -> Result<Vec<CommunityId>, LemmyError> {
|
||||||
if let Some(community_id) = community_id {
|
if let Some(community_id) = community_id {
|
||||||
// if the user provides a community_id, just check for mod/admin privileges
|
// if the user provides a community_id, just check for mod/admin privileges
|
||||||
is_mod_or_admin(pool, user_id, community_id).await?;
|
is_mod_or_admin(pool, person_id, community_id).await?;
|
||||||
Ok(vec![community_id])
|
Ok(vec![community_id])
|
||||||
} else {
|
} else {
|
||||||
let ids = blocking(pool, move |conn: &'_ _| {
|
let ids = blocking(pool, move |conn: &'_ _| {
|
||||||
CommunityModerator::get_user_moderated_communities(conn, user_id)
|
CommunityModerator::get_person_moderated_communities(conn, person_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
Ok(ids)
|
Ok(ids)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn check_optional_url(item: &Option<Option<String>>) -> Result<(), LemmyError> {
|
|
||||||
if let Some(Some(item)) = &item {
|
|
||||||
if Url::parse(item).is_err() {
|
|
||||||
return Err(ApiError::err("invalid_url").into());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn build_federated_instances(
|
pub(crate) async fn build_federated_instances(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<Option<FederatedInstances>, LemmyError> {
|
) -> Result<Option<FederatedInstances>, LemmyError> {
|
||||||
|
@ -245,17 +270,17 @@ pub async fn match_websocket_operation(
|
||||||
UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await,
|
UserOperation::Login => do_websocket_operation::<Login>(context, id, op, data).await,
|
||||||
UserOperation::Register => do_websocket_operation::<Register>(context, id, op, data).await,
|
UserOperation::Register => do_websocket_operation::<Register>(context, id, op, data).await,
|
||||||
UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await,
|
UserOperation::GetCaptcha => do_websocket_operation::<GetCaptcha>(context, id, op, data).await,
|
||||||
UserOperation::GetUserDetails => {
|
UserOperation::GetPersonDetails => {
|
||||||
do_websocket_operation::<GetUserDetails>(context, id, op, data).await
|
do_websocket_operation::<GetPersonDetails>(context, id, op, data).await
|
||||||
}
|
}
|
||||||
UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
|
UserOperation::GetReplies => do_websocket_operation::<GetReplies>(context, id, op, data).await,
|
||||||
UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
|
UserOperation::AddAdmin => do_websocket_operation::<AddAdmin>(context, id, op, data).await,
|
||||||
UserOperation::BanUser => do_websocket_operation::<BanUser>(context, id, op, data).await,
|
UserOperation::BanPerson => do_websocket_operation::<BanPerson>(context, id, op, data).await,
|
||||||
UserOperation::GetUserMentions => {
|
UserOperation::GetPersonMentions => {
|
||||||
do_websocket_operation::<GetUserMentions>(context, id, op, data).await
|
do_websocket_operation::<GetPersonMentions>(context, id, op, data).await
|
||||||
}
|
}
|
||||||
UserOperation::MarkUserMentionAsRead => {
|
UserOperation::MarkPersonMentionAsRead => {
|
||||||
do_websocket_operation::<MarkUserMentionAsRead>(context, id, op, data).await
|
do_websocket_operation::<MarkPersonMentionAsRead>(context, id, op, data).await
|
||||||
}
|
}
|
||||||
UserOperation::MarkAllAsRead => {
|
UserOperation::MarkAllAsRead => {
|
||||||
do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await
|
do_websocket_operation::<MarkAllAsRead>(context, id, op, data).await
|
||||||
|
@ -453,7 +478,11 @@ pub(crate) fn captcha_espeak_wav_base64(captcha: &str) -> Result<String, LemmyEr
|
||||||
pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
|
pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
|
||||||
// Make a temp file path
|
// Make a temp file path
|
||||||
let uuid = uuid::Uuid::new_v4().to_string();
|
let uuid = uuid::Uuid::new_v4().to_string();
|
||||||
let file_path = format!("/tmp/lemmy_espeak_{}.wav", &uuid);
|
let file_path = format!(
|
||||||
|
"{}/lemmy_espeak_{}.wav",
|
||||||
|
env::temp_dir().to_string_lossy(),
|
||||||
|
&uuid
|
||||||
|
);
|
||||||
|
|
||||||
// Write the wav file
|
// Write the wav file
|
||||||
Command::new("espeak")
|
Command::new("espeak")
|
||||||
|
@ -474,9 +503,81 @@ pub(crate) fn espeak_wav_base64(text: &str) -> Result<String, LemmyError> {
|
||||||
Ok(base64)
|
Ok(base64)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Checks the password length
|
||||||
|
pub(crate) fn password_length_check(pass: &str) -> Result<(), LemmyError> {
|
||||||
|
if pass.len() > 60 {
|
||||||
|
Err(ApiError::err("invalid_password").into())
|
||||||
|
} else {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::captcha_espeak_wav_base64;
|
use crate::{captcha_espeak_wav_base64, check_validator_time};
|
||||||
|
use lemmy_db_queries::{establish_unpooled_connection, source::local_user::LocalUser_, Crud};
|
||||||
|
use lemmy_db_schema::source::{
|
||||||
|
local_user::{LocalUser, LocalUserForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
|
};
|
||||||
|
use lemmy_utils::claims::Claims;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_should_not_validate_user_token_after_password_change() {
|
||||||
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
|
let new_person = PersonForm {
|
||||||
|
name: "Gerry9812".into(),
|
||||||
|
preferred_username: None,
|
||||||
|
avatar: None,
|
||||||
|
banner: None,
|
||||||
|
banned: None,
|
||||||
|
deleted: None,
|
||||||
|
published: None,
|
||||||
|
updated: None,
|
||||||
|
actor_id: None,
|
||||||
|
bio: None,
|
||||||
|
local: None,
|
||||||
|
private_key: None,
|
||||||
|
public_key: None,
|
||||||
|
last_refreshed_at: None,
|
||||||
|
inbox_url: None,
|
||||||
|
shared_inbox_url: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
|
let local_user_form = LocalUserForm {
|
||||||
|
person_id: inserted_person.id,
|
||||||
|
email: None,
|
||||||
|
matrix_user_id: None,
|
||||||
|
password_encrypted: "123456".to_string(),
|
||||||
|
admin: None,
|
||||||
|
show_nsfw: None,
|
||||||
|
theme: None,
|
||||||
|
default_sort_type: None,
|
||||||
|
default_listing_type: None,
|
||||||
|
lang: None,
|
||||||
|
show_avatars: None,
|
||||||
|
send_notifications_to_email: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let inserted_local_user = LocalUser::create(&conn, &local_user_form).unwrap();
|
||||||
|
|
||||||
|
let jwt = Claims::jwt(inserted_local_user.id.0).unwrap();
|
||||||
|
let claims = Claims::decode(&jwt).unwrap().claims;
|
||||||
|
let check = check_validator_time(&inserted_local_user.validator_time, &claims);
|
||||||
|
assert!(check.is_ok());
|
||||||
|
|
||||||
|
// The check should fail, since the validator time is now newer than the jwt issue time
|
||||||
|
let updated_local_user =
|
||||||
|
LocalUser::update_password(&conn, inserted_local_user.id, &"password111").unwrap();
|
||||||
|
let check_after = check_validator_time(&updated_local_user.validator_time, &claims);
|
||||||
|
assert!(check_after.is_err());
|
||||||
|
|
||||||
|
let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
assert_eq!(1, num_deleted);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_espeak() {
|
fn test_espeak() {
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,10 +1,9 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_community_ban,
|
check_community_ban,
|
||||||
check_downvotes_enabled,
|
check_downvotes_enabled,
|
||||||
check_optional_url,
|
|
||||||
collect_moderated_communities,
|
collect_moderated_communities,
|
||||||
get_user_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
get_user_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
is_mod_or_admin,
|
is_mod_or_admin,
|
||||||
Perform,
|
Perform,
|
||||||
};
|
};
|
||||||
|
@ -61,7 +60,7 @@ impl Perform for CreatePost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &CreatePost = &self;
|
let data: &CreatePost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.name)?;
|
check_slurs(&data.name)?;
|
||||||
check_slurs_opt(&data.body)?;
|
check_slurs_opt(&data.body)?;
|
||||||
|
@ -70,20 +69,19 @@ impl Perform for CreatePost {
|
||||||
return Err(ApiError::err("invalid_post_title").into());
|
return Err(ApiError::err("invalid_post_title").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
check_community_ban(user.id, data.community_id, context.pool()).await?;
|
check_community_ban(local_user_view.person.id, data.community_id, context.pool()).await?;
|
||||||
|
|
||||||
check_optional_url(&Some(data.url.to_owned()))?;
|
|
||||||
|
|
||||||
// Fetch Iframely and pictrs cached image
|
// Fetch Iframely and pictrs cached image
|
||||||
|
let data_url = data.url.as_ref();
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await;
|
fetch_iframely_and_pictrs_data(context.client(), data_url).await;
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.trim().to_owned(),
|
name: data.name.trim().to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data_url.map(|u| u.to_owned().into()),
|
||||||
body: data.body.to_owned(),
|
body: data.body.to_owned(),
|
||||||
community_id: data.community_id,
|
community_id: data.community_id,
|
||||||
creator_id: user.id,
|
creator_id: local_user_view.person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
nsfw: data.nsfw,
|
nsfw: data.nsfw,
|
||||||
|
@ -93,7 +91,7 @@ impl Perform for CreatePost {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: None,
|
ap_id: None,
|
||||||
local: true,
|
local: true,
|
||||||
published: None,
|
published: None,
|
||||||
|
@ -124,12 +122,14 @@ impl Perform for CreatePost {
|
||||||
Err(_e) => return Err(ApiError::err("couldnt_create_post").into()),
|
Err(_e) => return Err(ApiError::err("couldnt_create_post").into()),
|
||||||
};
|
};
|
||||||
|
|
||||||
updated_post.send_create(&user, context).await?;
|
updated_post
|
||||||
|
.send_create(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// They like their own post by default
|
// They like their own post by default
|
||||||
let like_form = PostLikeForm {
|
let like_form = PostLikeForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -138,12 +138,14 @@ impl Perform for CreatePost {
|
||||||
return Err(ApiError::err("couldnt_like_post").into());
|
return Err(ApiError::err("couldnt_like_post").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
updated_post.send_like(&user, context).await?;
|
updated_post
|
||||||
|
.send_like(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let inserted_post_id = inserted_post.id;
|
let inserted_post_id = inserted_post.id;
|
||||||
let post_view = match blocking(context.pool(), move |conn| {
|
let post_view = match blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, inserted_post_id, Some(user.id))
|
PostView::read(conn, inserted_post_id, Some(local_user_view.person.id))
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -173,12 +175,12 @@ impl Perform for GetPost {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetPostResponse, LemmyError> {
|
) -> Result<GetPostResponse, LemmyError> {
|
||||||
let data: &GetPost = &self;
|
let data: &GetPost = &self;
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let user_id = user.map(|u| u.id);
|
let person_id = local_user_view.map(|u| u.person.id);
|
||||||
|
|
||||||
let id = data.id;
|
let id = data.id;
|
||||||
let post_view = match blocking(context.pool(), move |conn| {
|
let post_view = match blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, id, user_id)
|
PostView::read(conn, id, person_id)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -189,7 +191,7 @@ impl Perform for GetPost {
|
||||||
let id = data.id;
|
let id = data.id;
|
||||||
let comments = blocking(context.pool(), move |conn| {
|
let comments = blocking(context.pool(), move |conn| {
|
||||||
CommentQueryBuilder::create(conn)
|
CommentQueryBuilder::create(conn)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.post_id(id)
|
.post_id(id)
|
||||||
.limit(9999)
|
.limit(9999)
|
||||||
.list()
|
.list()
|
||||||
|
@ -204,7 +206,7 @@ impl Perform for GetPost {
|
||||||
|
|
||||||
// Necessary for the sidebar
|
// Necessary for the sidebar
|
||||||
let community_view = match blocking(context.pool(), move |conn| {
|
let community_view = match blocking(context.pool(), move |conn| {
|
||||||
CommunityView::read(conn, community_id, user_id)
|
CommunityView::read(conn, community_id, person_id)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -239,15 +241,15 @@ impl Perform for GetPosts {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetPostsResponse, LemmyError> {
|
) -> Result<GetPostsResponse, LemmyError> {
|
||||||
let data: &GetPosts = &self;
|
let data: &GetPosts = &self;
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = match &user {
|
let person_id = match &local_user_view {
|
||||||
Some(user) => Some(user.id),
|
Some(uv) => Some(uv.person.id),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let show_nsfw = match &user {
|
let show_nsfw = match &local_user_view {
|
||||||
Some(user) => user.show_nsfw,
|
Some(uv) => uv.local_user.show_nsfw,
|
||||||
None => false,
|
None => false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -265,7 +267,7 @@ impl Perform for GetPosts {
|
||||||
.show_nsfw(show_nsfw)
|
.show_nsfw(show_nsfw)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.community_name(community_name)
|
.community_name(community_name)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -290,7 +292,7 @@ impl Perform for CreatePostLike {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &CreatePostLike = &self;
|
let data: &CreatePostLike = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Don't do a downvote if site has downvotes disabled
|
// Don't do a downvote if site has downvotes disabled
|
||||||
check_downvotes_enabled(data.score, context.pool()).await?;
|
check_downvotes_enabled(data.score, context.pool()).await?;
|
||||||
|
@ -299,18 +301,18 @@ impl Perform for CreatePostLike {
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, post.community_id, context.pool()).await?;
|
check_community_ban(local_user_view.person.id, post.community_id, context.pool()).await?;
|
||||||
|
|
||||||
let like_form = PostLikeForm {
|
let like_form = PostLikeForm {
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
score: data.score,
|
score: data.score,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Remove any likes first
|
// Remove any likes first
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
PostLike::remove(conn, user_id, post_id)
|
PostLike::remove(conn, person_id, post_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -324,18 +326,20 @@ impl Perform for CreatePostLike {
|
||||||
}
|
}
|
||||||
|
|
||||||
if like_form.score == 1 {
|
if like_form.score == 1 {
|
||||||
post.send_like(&user, context).await?;
|
post.send_like(&local_user_view.person, context).await?;
|
||||||
} else if like_form.score == -1 {
|
} else if like_form.score == -1 {
|
||||||
post.send_dislike(&user, context).await?;
|
post.send_dislike(&local_user_view.person, context).await?;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
post.send_undo_like(&user, context).await?;
|
post
|
||||||
|
.send_undo_like(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let post_view = match blocking(context.pool(), move |conn| {
|
let post_view = match blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user_id))
|
PostView::read(conn, post_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
{
|
{
|
||||||
|
@ -365,7 +369,7 @@ impl Perform for EditPost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &EditPost = &self;
|
let data: &EditPost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.name)?;
|
check_slurs(&data.name)?;
|
||||||
check_slurs_opt(&data.body)?;
|
check_slurs_opt(&data.body)?;
|
||||||
|
@ -377,20 +381,26 @@ impl Perform for EditPost {
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_post.community_id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the creator can edit
|
// Verify that only the creator can edit
|
||||||
if !Post::is_post_creator(user.id, orig_post.creator_id) {
|
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
|
||||||
return Err(ApiError::err("no_post_edit_allowed").into());
|
return Err(ApiError::err("no_post_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fetch Iframely and Pictrs cached image
|
// Fetch Iframely and Pictrs cached image
|
||||||
|
let data_url = data.url.as_ref();
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
fetch_iframely_and_pictrs_data(context.client(), data.url.to_owned()).await;
|
fetch_iframely_and_pictrs_data(context.client(), data_url).await;
|
||||||
|
|
||||||
let post_form = PostForm {
|
let post_form = PostForm {
|
||||||
name: data.name.trim().to_owned(),
|
name: data.name.trim().to_owned(),
|
||||||
url: data.url.to_owned(),
|
url: data_url.map(|u| u.to_owned().into()),
|
||||||
body: data.body.to_owned(),
|
body: data.body.to_owned(),
|
||||||
nsfw: data.nsfw,
|
nsfw: data.nsfw,
|
||||||
creator_id: orig_post.creator_id.to_owned(),
|
creator_id: orig_post.creator_id.to_owned(),
|
||||||
|
@ -403,7 +413,7 @@ impl Perform for EditPost {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: Some(orig_post.ap_id),
|
ap_id: Some(orig_post.ap_id),
|
||||||
local: orig_post.local,
|
local: orig_post.local,
|
||||||
published: None,
|
published: None,
|
||||||
|
@ -428,11 +438,13 @@ impl Perform for EditPost {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Send apub update
|
// Send apub update
|
||||||
updated_post.send_update(&user, context).await?;
|
updated_post
|
||||||
|
.send_update(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user.id))
|
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -458,15 +470,20 @@ impl Perform for DeletePost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &DeletePost = &self;
|
let data: &DeletePost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_post.community_id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the creator can delete
|
// Verify that only the creator can delete
|
||||||
if !Post::is_post_creator(user.id, orig_post.creator_id) {
|
if !Post::is_post_creator(local_user_view.person.id, orig_post.creator_id) {
|
||||||
return Err(ApiError::err("no_post_edit_allowed").into());
|
return Err(ApiError::err("no_post_edit_allowed").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,15 +497,19 @@ impl Perform for DeletePost {
|
||||||
|
|
||||||
// apub updates
|
// apub updates
|
||||||
if deleted {
|
if deleted {
|
||||||
updated_post.send_delete(&user, context).await?;
|
updated_post
|
||||||
|
.send_delete(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
updated_post.send_undo_delete(&user, context).await?;
|
updated_post
|
||||||
|
.send_undo_delete(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refetch the post
|
// Refetch the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user.id))
|
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -514,15 +535,25 @@ impl Perform for RemovePost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &RemovePost = &self;
|
let data: &RemovePost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_post.community_id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the mods can remove
|
// Verify that only the mods can remove
|
||||||
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?;
|
is_mod_or_admin(
|
||||||
|
context.pool(),
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -534,7 +565,7 @@ impl Perform for RemovePost {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModRemovePostForm {
|
let form = ModRemovePostForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
removed: Some(removed),
|
removed: Some(removed),
|
||||||
reason: data.reason.to_owned(),
|
reason: data.reason.to_owned(),
|
||||||
|
@ -546,16 +577,20 @@ impl Perform for RemovePost {
|
||||||
|
|
||||||
// apub updates
|
// apub updates
|
||||||
if removed {
|
if removed {
|
||||||
updated_post.send_remove(&user, context).await?;
|
updated_post
|
||||||
|
.send_remove(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
} else {
|
} else {
|
||||||
updated_post.send_undo_remove(&user, context).await?;
|
updated_post
|
||||||
|
.send_undo_remove(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Refetch the post
|
// Refetch the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user_id))
|
PostView::read(conn, post_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -581,15 +616,25 @@ impl Perform for LockPost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &LockPost = &self;
|
let data: &LockPost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_post.community_id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the mods can lock
|
// Verify that only the mods can lock
|
||||||
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?;
|
is_mod_or_admin(
|
||||||
|
context.pool(),
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -601,19 +646,21 @@ impl Perform for LockPost {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModLockPostForm {
|
let form = ModLockPostForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
locked: Some(locked),
|
locked: Some(locked),
|
||||||
};
|
};
|
||||||
blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
|
blocking(context.pool(), move |conn| ModLockPost::create(conn, &form)).await??;
|
||||||
|
|
||||||
// apub updates
|
// apub updates
|
||||||
updated_post.send_update(&user, context).await?;
|
updated_post
|
||||||
|
.send_update(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Refetch the post
|
// Refetch the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user.id))
|
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -639,15 +686,25 @@ impl Perform for StickyPost {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &StickyPost = &self;
|
let data: &StickyPost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let orig_post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
check_community_ban(user.id, orig_post.community_id, context.pool()).await?;
|
check_community_ban(
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
context.pool(),
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Verify that only the mods can sticky
|
// Verify that only the mods can sticky
|
||||||
is_mod_or_admin(context.pool(), user.id, orig_post.community_id).await?;
|
is_mod_or_admin(
|
||||||
|
context.pool(),
|
||||||
|
local_user_view.person.id,
|
||||||
|
orig_post.community_id,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Update the post
|
// Update the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
|
@ -659,7 +716,7 @@ impl Perform for StickyPost {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModStickyPostForm {
|
let form = ModStickyPostForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
stickied: Some(stickied),
|
stickied: Some(stickied),
|
||||||
};
|
};
|
||||||
|
@ -670,12 +727,14 @@ impl Perform for StickyPost {
|
||||||
|
|
||||||
// Apub updates
|
// Apub updates
|
||||||
// TODO stickied should pry work like locked for ease of use
|
// TODO stickied should pry work like locked for ease of use
|
||||||
updated_post.send_update(&user, context).await?;
|
updated_post
|
||||||
|
.send_update(&local_user_view.person, context)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Refetch the post
|
// Refetch the post
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user.id))
|
PostView::read(conn, post_id, Some(local_user_view.person.id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -701,11 +760,11 @@ impl Perform for SavePost {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<PostResponse, LemmyError> {
|
) -> Result<PostResponse, LemmyError> {
|
||||||
let data: &SavePost = &self;
|
let data: &SavePost = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let post_saved_form = PostSavedForm {
|
let post_saved_form = PostSavedForm {
|
||||||
post_id: data.post_id,
|
post_id: data.post_id,
|
||||||
user_id: user.id,
|
person_id: local_user_view.person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
if data.save {
|
if data.save {
|
||||||
|
@ -721,9 +780,9 @@ impl Perform for SavePost {
|
||||||
}
|
}
|
||||||
|
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(conn, post_id, Some(user_id))
|
PostView::read(conn, post_id, Some(person_id))
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -742,7 +801,7 @@ impl Perform for CreatePostReport {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<CreatePostReportResponse, LemmyError> {
|
) -> Result<CreatePostReportResponse, LemmyError> {
|
||||||
let data: &CreatePostReport = &self;
|
let data: &CreatePostReport = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// check size of report and check for whitespace
|
// check size of report and check for whitespace
|
||||||
let reason = data.reason.trim();
|
let reason = data.reason.trim();
|
||||||
|
@ -753,17 +812,17 @@ impl Perform for CreatePostReport {
|
||||||
return Err(ApiError::err("report_too_long").into());
|
return Err(ApiError::err("report_too_long").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let post_id = data.post_id;
|
let post_id = data.post_id;
|
||||||
let post_view = blocking(context.pool(), move |conn| {
|
let post_view = blocking(context.pool(), move |conn| {
|
||||||
PostView::read(&conn, post_id, None)
|
PostView::read(&conn, post_id, None)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
check_community_ban(user_id, post_view.community.id, context.pool()).await?;
|
check_community_ban(person_id, post_view.community.id, context.pool()).await?;
|
||||||
|
|
||||||
let report_form = PostReportForm {
|
let report_form = PostReportForm {
|
||||||
creator_id: user_id,
|
creator_id: person_id,
|
||||||
post_id,
|
post_id,
|
||||||
original_post_name: post_view.post.name,
|
original_post_name: post_view.post.name,
|
||||||
original_post_url: post_view.post.url,
|
original_post_url: post_view.post.url,
|
||||||
|
@ -785,7 +844,7 @@ impl Perform for CreatePostReport {
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::CreatePostReport,
|
op: UserOperation::CreatePostReport,
|
||||||
response: res.clone(),
|
response: res.clone(),
|
||||||
recipient_id: user.id,
|
local_recipient_id: local_user_view.local_user.id,
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -811,7 +870,7 @@ impl Perform for ResolvePostReport {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<ResolvePostReportResponse, LemmyError> {
|
) -> Result<ResolvePostReportResponse, LemmyError> {
|
||||||
let data: &ResolvePostReport = &self;
|
let data: &ResolvePostReport = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let report_id = data.report_id;
|
let report_id = data.report_id;
|
||||||
let report = blocking(context.pool(), move |conn| {
|
let report = blocking(context.pool(), move |conn| {
|
||||||
|
@ -819,15 +878,15 @@ impl Perform for ResolvePostReport {
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
is_mod_or_admin(context.pool(), user_id, report.community.id).await?;
|
is_mod_or_admin(context.pool(), person_id, report.community.id).await?;
|
||||||
|
|
||||||
let resolved = data.resolved;
|
let resolved = data.resolved;
|
||||||
let resolve_fun = move |conn: &'_ _| {
|
let resolve_fun = move |conn: &'_ _| {
|
||||||
if resolved {
|
if resolved {
|
||||||
PostReport::resolve(conn, report_id, user_id)
|
PostReport::resolve(conn, report_id, person_id)
|
||||||
} else {
|
} else {
|
||||||
PostReport::unresolve(conn, report_id, user_id)
|
PostReport::unresolve(conn, report_id, person_id)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -863,12 +922,12 @@ impl Perform for ListPostReports {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<ListPostReportsResponse, LemmyError> {
|
) -> Result<ListPostReportsResponse, LemmyError> {
|
||||||
let data: &ListPostReports = &self;
|
let data: &ListPostReports = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = local_user_view.person.id;
|
||||||
let community_id = data.community;
|
let community_id = data.community;
|
||||||
let community_ids =
|
let community_ids =
|
||||||
collect_moderated_communities(user_id, community_id, context.pool()).await?;
|
collect_moderated_communities(person_id, community_id, context.pool()).await?;
|
||||||
|
|
||||||
let page = data.page;
|
let page = data.page;
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
|
@ -886,7 +945,7 @@ impl Perform for ListPostReports {
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::ListPostReports,
|
op: UserOperation::ListPostReports,
|
||||||
response: res.clone(),
|
response: res.clone(),
|
||||||
recipient_id: user.id,
|
local_recipient_id: local_user_view.local_user.id,
|
||||||
websocket_id,
|
websocket_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Perform;
|
use crate::Perform;
|
||||||
use actix_web::{error::ErrorBadRequest, *};
|
use actix_web::{error::ErrorBadRequest, *};
|
||||||
use lemmy_api_structs::{comment::*, community::*, post::*, site::*, user::*, websocket::*};
|
use lemmy_api_structs::{comment::*, community::*, person::*, post::*, site::*, websocket::*};
|
||||||
use lemmy_utils::rate_limit::RateLimit;
|
use lemmy_utils::rate_limit::RateLimit;
|
||||||
use lemmy_websocket::{routes::chat_route, LemmyContext};
|
use lemmy_websocket::{routes::chat_route, LemmyContext};
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -137,11 +137,11 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
|
||||||
.service(
|
.service(
|
||||||
web::scope("/user")
|
web::scope("/user")
|
||||||
.wrap(rate_limit.message())
|
.wrap(rate_limit.message())
|
||||||
.route("", web::get().to(route_get::<GetUserDetails>))
|
.route("", web::get().to(route_get::<GetPersonDetails>))
|
||||||
.route("/mention", web::get().to(route_get::<GetUserMentions>))
|
.route("/mention", web::get().to(route_get::<GetPersonMentions>))
|
||||||
.route(
|
.route(
|
||||||
"/mention/mark_as_read",
|
"/mention/mark_as_read",
|
||||||
web::post().to(route_post::<MarkUserMentionAsRead>),
|
web::post().to(route_post::<MarkPersonMentionAsRead>),
|
||||||
)
|
)
|
||||||
.route("/replies", web::get().to(route_get::<GetReplies>))
|
.route("/replies", web::get().to(route_get::<GetReplies>))
|
||||||
.route(
|
.route(
|
||||||
|
@ -150,7 +150,7 @@ pub fn config(cfg: &mut web::ServiceConfig, rate_limit: &RateLimit) {
|
||||||
)
|
)
|
||||||
.route("/join", web::post().to(route_post::<UserJoin>))
|
.route("/join", web::post().to(route_post::<UserJoin>))
|
||||||
// Admin action. I don't like that it's in /user
|
// Admin action. I don't like that it's in /user
|
||||||
.route("/ban", web::post().to(route_post::<BanUser>))
|
.route("/ban", web::post().to(route_post::<BanPerson>))
|
||||||
// Account actions. I don't like that they're in /user maybe /accounts
|
// Account actions. I don't like that they're in /user maybe /accounts
|
||||||
.route("/login", web::post().to(route_post::<Login>))
|
.route("/login", web::post().to(route_post::<Login>))
|
||||||
.route("/get_captcha", web::get().to(route_get::<GetCaptcha>))
|
.route("/get_captcha", web::get().to(route_get::<GetCaptcha>))
|
||||||
|
|
|
@ -1,17 +1,23 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
build_federated_instances,
|
build_federated_instances,
|
||||||
get_user_from_jwt,
|
get_local_user_settings_view_from_jwt,
|
||||||
get_user_from_jwt_opt,
|
get_local_user_settings_view_from_jwt_opt,
|
||||||
get_user_safe_settings_from_jwt,
|
get_local_user_view_from_jwt,
|
||||||
get_user_safe_settings_from_jwt_opt,
|
get_local_user_view_from_jwt_opt,
|
||||||
is_admin,
|
is_admin,
|
||||||
Perform,
|
Perform,
|
||||||
};
|
};
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_structs::{blocking, site::*, user::Register};
|
use lemmy_api_structs::{blocking, person::Register, site::*};
|
||||||
use lemmy_apub::fetcher::search::search_by_apub_id;
|
use lemmy_apub::fetcher::search::search_by_apub_id;
|
||||||
use lemmy_db_queries::{diesel_option_overwrite, source::site::Site_, Crud, SearchType, SortType};
|
use lemmy_db_queries::{
|
||||||
|
diesel_option_overwrite_to_url,
|
||||||
|
source::site::Site_,
|
||||||
|
Crud,
|
||||||
|
SearchType,
|
||||||
|
SortType,
|
||||||
|
};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::{
|
source::{
|
||||||
|
@ -26,7 +32,7 @@ use lemmy_db_views::{
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_view::CommunityQueryBuilder,
|
community_view::CommunityQueryBuilder,
|
||||||
user_view::{UserQueryBuilder, UserViewSafe},
|
person_view::{PersonQueryBuilder, PersonViewSafe},
|
||||||
};
|
};
|
||||||
use lemmy_db_views_moderator::{
|
use lemmy_db_views_moderator::{
|
||||||
mod_add_community_view::ModAddCommunityView,
|
mod_add_community_view::ModAddCommunityView,
|
||||||
|
@ -68,36 +74,36 @@ impl Perform for GetModlog {
|
||||||
let data: &GetModlog = &self;
|
let data: &GetModlog = &self;
|
||||||
|
|
||||||
let community_id = data.community_id;
|
let community_id = data.community_id;
|
||||||
let mod_user_id = data.mod_user_id;
|
let mod_person_id = data.mod_person_id;
|
||||||
let page = data.page;
|
let page = data.page;
|
||||||
let limit = data.limit;
|
let limit = data.limit;
|
||||||
let removed_posts = blocking(context.pool(), move |conn| {
|
let removed_posts = blocking(context.pool(), move |conn| {
|
||||||
ModRemovePostView::list(conn, community_id, mod_user_id, page, limit)
|
ModRemovePostView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let locked_posts = blocking(context.pool(), move |conn| {
|
let locked_posts = blocking(context.pool(), move |conn| {
|
||||||
ModLockPostView::list(conn, community_id, mod_user_id, page, limit)
|
ModLockPostView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let stickied_posts = blocking(context.pool(), move |conn| {
|
let stickied_posts = blocking(context.pool(), move |conn| {
|
||||||
ModStickyPostView::list(conn, community_id, mod_user_id, page, limit)
|
ModStickyPostView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let removed_comments = blocking(context.pool(), move |conn| {
|
let removed_comments = blocking(context.pool(), move |conn| {
|
||||||
ModRemoveCommentView::list(conn, community_id, mod_user_id, page, limit)
|
ModRemoveCommentView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let banned_from_community = blocking(context.pool(), move |conn| {
|
let banned_from_community = blocking(context.pool(), move |conn| {
|
||||||
ModBanFromCommunityView::list(conn, community_id, mod_user_id, page, limit)
|
ModBanFromCommunityView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let added_to_community = blocking(context.pool(), move |conn| {
|
let added_to_community = blocking(context.pool(), move |conn| {
|
||||||
ModAddCommunityView::list(conn, community_id, mod_user_id, page, limit)
|
ModAddCommunityView::list(conn, community_id, mod_person_id, page, limit)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -105,9 +111,9 @@ impl Perform for GetModlog {
|
||||||
let (removed_communities, banned, added) = if data.community_id.is_none() {
|
let (removed_communities, banned, added) = if data.community_id.is_none() {
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
Ok((
|
Ok((
|
||||||
ModRemoveCommunityView::list(conn, mod_user_id, page, limit)?,
|
ModRemoveCommunityView::list(conn, mod_person_id, page, limit)?,
|
||||||
ModBanView::list(conn, mod_user_id, page, limit)?,
|
ModBanView::list(conn, mod_person_id, page, limit)?,
|
||||||
ModAddView::list(conn, mod_user_id, page, limit)?,
|
ModAddView::list(conn, mod_person_id, page, limit)?,
|
||||||
)) as Result<_, LemmyError>
|
)) as Result<_, LemmyError>
|
||||||
})
|
})
|
||||||
.await??
|
.await??
|
||||||
|
@ -146,20 +152,20 @@ impl Perform for CreateSite {
|
||||||
return Err(ApiError::err("site_already_exists").into());
|
return Err(ApiError::err("site_already_exists").into());
|
||||||
};
|
};
|
||||||
|
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.name)?;
|
check_slurs(&data.name)?;
|
||||||
check_slurs_opt(&data.description)?;
|
check_slurs_opt(&data.description)?;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
description: data.description.to_owned(),
|
description: data.description.to_owned(),
|
||||||
icon: Some(data.icon.to_owned()),
|
icon: Some(data.icon.to_owned().map(|url| url.into())),
|
||||||
banner: Some(data.banner.to_owned()),
|
banner: Some(data.banner.to_owned().map(|url| url.into())),
|
||||||
creator_id: user.id,
|
creator_id: local_user_view.person.id,
|
||||||
enable_downvotes: data.enable_downvotes,
|
enable_downvotes: data.enable_downvotes,
|
||||||
open_registration: data.open_registration,
|
open_registration: data.open_registration,
|
||||||
enable_nsfw: data.enable_nsfw,
|
enable_nsfw: data.enable_nsfw,
|
||||||
|
@ -186,18 +192,18 @@ impl Perform for EditSite {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<SiteResponse, LemmyError> {
|
) -> Result<SiteResponse, LemmyError> {
|
||||||
let data: &EditSite = &self;
|
let data: &EditSite = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
check_slurs(&data.name)?;
|
check_slurs(&data.name)?;
|
||||||
check_slurs_opt(&data.description)?;
|
check_slurs_opt(&data.description)?;
|
||||||
|
|
||||||
// Make sure user is an admin
|
// Make sure user is an admin
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
let found_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
||||||
|
|
||||||
let icon = diesel_option_overwrite(&data.icon);
|
let icon = diesel_option_overwrite_to_url(&data.icon)?;
|
||||||
let banner = diesel_option_overwrite(&data.banner);
|
let banner = diesel_option_overwrite_to_url(&data.banner)?;
|
||||||
|
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: data.name.to_owned(),
|
name: data.name.to_owned(),
|
||||||
|
@ -277,20 +283,20 @@ impl Perform for GetSite {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
|
||||||
|
|
||||||
// Make sure the site creator is the top admin
|
// Make sure the site creator is the top admin
|
||||||
if let Some(site_view) = site_view.to_owned() {
|
if let Some(site_view) = site_view.to_owned() {
|
||||||
let site_creator_id = site_view.creator.id;
|
let site_creator_id = site_view.creator.id;
|
||||||
// TODO investigate why this is sometimes coming back null
|
// TODO investigate why this is sometimes coming back null
|
||||||
// Maybe user_.admin isn't being set to true?
|
// Maybe user_.admin isn't being set to true?
|
||||||
if let Some(creator_index) = admins.iter().position(|r| r.user.id == site_creator_id) {
|
if let Some(creator_index) = admins.iter().position(|r| r.person.id == site_creator_id) {
|
||||||
let creator_user = admins.remove(creator_index);
|
let creator_person = admins.remove(creator_index);
|
||||||
admins.insert(0, creator_user);
|
admins.insert(0, creator_person);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
|
let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
|
||||||
|
|
||||||
let online = context
|
let online = context
|
||||||
.chat_server()
|
.chat_server()
|
||||||
|
@ -298,7 +304,7 @@ impl Perform for GetSite {
|
||||||
.await
|
.await
|
||||||
.unwrap_or(1);
|
.unwrap_or(1);
|
||||||
|
|
||||||
let my_user = get_user_safe_settings_from_jwt_opt(&data.auth, context.pool()).await?;
|
let my_user = get_local_user_settings_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let federated_instances = build_federated_instances(context.pool()).await?;
|
let federated_instances = build_federated_instances(context.pool()).await?;
|
||||||
|
|
||||||
Ok(GetSiteResponse {
|
Ok(GetSiteResponse {
|
||||||
|
@ -329,8 +335,8 @@ impl Perform for Search {
|
||||||
Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e),
|
Err(e) => debug!("Failed to resolve search query as activitypub ID: {}", e),
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = get_user_from_jwt_opt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt_opt(&data.auth, context.pool()).await?;
|
||||||
let user_id = user.map(|u| u.id);
|
let person_id = local_user_view.map(|u| u.person.id);
|
||||||
|
|
||||||
let type_ = SearchType::from_str(&data.type_)?;
|
let type_ = SearchType::from_str(&data.type_)?;
|
||||||
|
|
||||||
|
@ -355,7 +361,7 @@ impl Perform for Search {
|
||||||
.show_nsfw(true)
|
.show_nsfw(true)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.community_name(community_name)
|
.community_name(community_name)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
|
@ -368,7 +374,7 @@ impl Perform for Search {
|
||||||
CommentQueryBuilder::create(&conn)
|
CommentQueryBuilder::create(&conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -380,7 +386,7 @@ impl Perform for Search {
|
||||||
CommunityQueryBuilder::create(conn)
|
CommunityQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -389,7 +395,7 @@ impl Perform for Search {
|
||||||
}
|
}
|
||||||
SearchType::Users => {
|
SearchType::Users => {
|
||||||
users = blocking(context.pool(), move |conn| {
|
users = blocking(context.pool(), move |conn| {
|
||||||
UserQueryBuilder::create(conn)
|
PersonQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.page(page)
|
.page(page)
|
||||||
|
@ -405,7 +411,7 @@ impl Perform for Search {
|
||||||
.show_nsfw(true)
|
.show_nsfw(true)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.community_name(community_name)
|
.community_name(community_name)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
|
@ -420,7 +426,7 @@ impl Perform for Search {
|
||||||
CommentQueryBuilder::create(conn)
|
CommentQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -434,7 +440,7 @@ impl Perform for Search {
|
||||||
CommunityQueryBuilder::create(conn)
|
CommunityQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.page(page)
|
.page(page)
|
||||||
.limit(limit)
|
.limit(limit)
|
||||||
.list()
|
.list()
|
||||||
|
@ -445,7 +451,7 @@ impl Perform for Search {
|
||||||
let sort = SortType::from_str(&data.sort)?;
|
let sort = SortType::from_str(&data.sort)?;
|
||||||
|
|
||||||
users = blocking(context.pool(), move |conn| {
|
users = blocking(context.pool(), move |conn| {
|
||||||
UserQueryBuilder::create(conn)
|
PersonQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.search_term(q)
|
.search_term(q)
|
||||||
.page(page)
|
.page(page)
|
||||||
|
@ -459,7 +465,7 @@ impl Perform for Search {
|
||||||
PostQueryBuilder::create(conn)
|
PostQueryBuilder::create(conn)
|
||||||
.sort(&sort)
|
.sort(&sort)
|
||||||
.show_nsfw(true)
|
.show_nsfw(true)
|
||||||
.my_user_id(user_id)
|
.my_person_id(person_id)
|
||||||
.community_id(community_id)
|
.community_id(community_id)
|
||||||
.community_name(community_name)
|
.community_name(community_name)
|
||||||
.url_search(q)
|
.url_search(q)
|
||||||
|
@ -492,18 +498,18 @@ impl Perform for TransferSite {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetSiteResponse, LemmyError> {
|
) -> Result<GetSiteResponse, LemmyError> {
|
||||||
let data: &TransferSite = &self;
|
let data: &TransferSite = &self;
|
||||||
let user = get_user_safe_settings_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
let read_site = blocking(context.pool(), move |conn| Site::read_simple(conn)).await??;
|
||||||
|
|
||||||
// Make sure user is the creator
|
// Make sure user is the creator
|
||||||
if read_site.creator_id != user.id {
|
if read_site.creator_id != local_user_view.person.id {
|
||||||
return Err(ApiError::err("not_an_admin").into());
|
return Err(ApiError::err("not_an_admin").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_creator_id = data.user_id;
|
let new_creator_id = data.person_id;
|
||||||
let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id);
|
let transfer_site = move |conn: &'_ _| Site::transfer(conn, new_creator_id);
|
||||||
if blocking(context.pool(), transfer_site).await?.is_err() {
|
if blocking(context.pool(), transfer_site).await?.is_err() {
|
||||||
return Err(ApiError::err("couldnt_update_site").into());
|
return Err(ApiError::err("couldnt_update_site").into());
|
||||||
|
@ -511,8 +517,8 @@ impl Perform for TransferSite {
|
||||||
|
|
||||||
// Mod tables
|
// Mod tables
|
||||||
let form = ModAddForm {
|
let form = ModAddForm {
|
||||||
mod_user_id: user.id,
|
mod_person_id: local_user_view.person.id,
|
||||||
other_user_id: data.user_id,
|
other_person_id: data.person_id,
|
||||||
removed: Some(false),
|
removed: Some(false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -520,24 +526,26 @@ impl Perform for TransferSite {
|
||||||
|
|
||||||
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
let site_view = blocking(context.pool(), move |conn| SiteView::read(conn)).await??;
|
||||||
|
|
||||||
let mut admins = blocking(context.pool(), move |conn| UserViewSafe::admins(conn)).await??;
|
let mut admins = blocking(context.pool(), move |conn| PersonViewSafe::admins(conn)).await??;
|
||||||
let creator_index = admins
|
let creator_index = admins
|
||||||
.iter()
|
.iter()
|
||||||
.position(|r| r.user.id == site_view.creator.id)
|
.position(|r| r.person.id == site_view.creator.id)
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let creator_user = admins.remove(creator_index);
|
let creator_person = admins.remove(creator_index);
|
||||||
admins.insert(0, creator_user);
|
admins.insert(0, creator_person);
|
||||||
|
|
||||||
let banned = blocking(context.pool(), move |conn| UserViewSafe::banned(conn)).await??;
|
let banned = blocking(context.pool(), move |conn| PersonViewSafe::banned(conn)).await??;
|
||||||
let federated_instances = build_federated_instances(context.pool()).await?;
|
let federated_instances = build_federated_instances(context.pool()).await?;
|
||||||
|
|
||||||
|
let my_user = Some(get_local_user_settings_view_from_jwt(&data.auth, context.pool()).await?);
|
||||||
|
|
||||||
Ok(GetSiteResponse {
|
Ok(GetSiteResponse {
|
||||||
site_view: Some(site_view),
|
site_view: Some(site_view),
|
||||||
admins,
|
admins,
|
||||||
banned,
|
banned,
|
||||||
online: 0,
|
online: 0,
|
||||||
version: version::VERSION.to_string(),
|
version: version::VERSION.to_string(),
|
||||||
my_user: Some(user),
|
my_user,
|
||||||
federated_instances,
|
federated_instances,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -553,10 +561,10 @@ impl Perform for GetSiteConfig {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetSiteConfigResponse, LemmyError> {
|
) -> Result<GetSiteConfigResponse, LemmyError> {
|
||||||
let data: &GetSiteConfig = &self;
|
let data: &GetSiteConfig = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Only let admins read this
|
// Only let admins read this
|
||||||
is_admin(context.pool(), user.id).await?;
|
is_admin(&local_user_view)?;
|
||||||
|
|
||||||
let config_hjson = Settings::read_config_file()?;
|
let config_hjson = Settings::read_config_file()?;
|
||||||
|
|
||||||
|
@ -574,11 +582,10 @@ impl Perform for SaveSiteConfig {
|
||||||
_websocket_id: Option<ConnectionId>,
|
_websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<GetSiteConfigResponse, LemmyError> {
|
) -> Result<GetSiteConfigResponse, LemmyError> {
|
||||||
let data: &SaveSiteConfig = &self;
|
let data: &SaveSiteConfig = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
// Only let admins read this
|
// Only let admins read this
|
||||||
let user_id = user.id;
|
is_admin(&local_user_view)?;
|
||||||
is_admin(context.pool(), user_id).await?;
|
|
||||||
|
|
||||||
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
|
// Make sure docker doesn't have :ro at the end of the volume, so its not a read-only filesystem
|
||||||
let config_hjson = match Settings::save_config_file(&data.config_hjson) {
|
let config_hjson = match Settings::save_config_file(&data.config_hjson) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{get_user_from_jwt, Perform};
|
use crate::{get_local_user_view_from_jwt, Perform};
|
||||||
use actix_web::web::Data;
|
use actix_web::web::Data;
|
||||||
use lemmy_api_structs::websocket::*;
|
use lemmy_api_structs::websocket::*;
|
||||||
use lemmy_utils::{ConnectionId, LemmyError};
|
use lemmy_utils::{ConnectionId, LemmyError};
|
||||||
|
@ -17,11 +17,11 @@ impl Perform for UserJoin {
|
||||||
websocket_id: Option<ConnectionId>,
|
websocket_id: Option<ConnectionId>,
|
||||||
) -> Result<UserJoinResponse, LemmyError> {
|
) -> Result<UserJoinResponse, LemmyError> {
|
||||||
let data: &UserJoin = &self;
|
let data: &UserJoin = &self;
|
||||||
let user = get_user_from_jwt(&data.auth, context.pool()).await?;
|
let local_user_view = get_local_user_view_from_jwt(&data.auth, context.pool()).await?;
|
||||||
|
|
||||||
if let Some(ws_id) = websocket_id {
|
if let Some(ws_id) = websocket_id {
|
||||||
context.chat_server().do_send(JoinUserRoom {
|
context.chat_server().do_send(JoinUserRoom {
|
||||||
user_id: user.id,
|
local_user_id: local_user_view.local_user.id,
|
||||||
id: ws_id,
|
id: ws_id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,4 +21,4 @@ diesel = "1.4.5"
|
||||||
actix-web = "3.3.2"
|
actix-web = "3.3.2"
|
||||||
chrono = { version = "0.4.19", features = ["serde"] }
|
chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
||||||
url = "2.2.0"
|
url = "2.2.1"
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
|
use lemmy_db_schema::{CommentId, CommunityId, LocalUserId, PostId};
|
||||||
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
|
use lemmy_db_views::{comment_report_view::CommentReportView, comment_view::CommentView};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreateComment {
|
pub struct CreateComment {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub parent_id: Option<i32>,
|
pub parent_id: Option<CommentId>,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub form_id: Option<String>,
|
pub form_id: Option<String>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -13,21 +14,21 @@ pub struct CreateComment {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct EditComment {
|
pub struct EditComment {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub form_id: Option<String>,
|
pub form_id: Option<String>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DeleteComment {
|
pub struct DeleteComment {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct RemoveComment {
|
pub struct RemoveComment {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
@ -35,14 +36,14 @@ pub struct RemoveComment {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct MarkCommentAsRead {
|
pub struct MarkCommentAsRead {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub read: bool,
|
pub read: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct SaveComment {
|
pub struct SaveComment {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub save: bool,
|
pub save: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -50,13 +51,13 @@ pub struct SaveComment {
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct CommentResponse {
|
pub struct CommentResponse {
|
||||||
pub comment_view: CommentView,
|
pub comment_view: CommentView,
|
||||||
pub recipient_ids: Vec<i32>, // TODO another way to do this? Maybe a UserMention belongs to Comment
|
pub recipient_ids: Vec<LocalUserId>,
|
||||||
pub form_id: Option<String>, // An optional front end ID, to tell which is coming back
|
pub form_id: Option<String>, // An optional front end ID, to tell which is coming back
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreateCommentLike {
|
pub struct CreateCommentLike {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -67,7 +68,7 @@ pub struct GetComments {
|
||||||
pub sort: String,
|
pub sort: String,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
pub community_id: Option<i32>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub community_name: Option<String>,
|
pub community_name: Option<String>,
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -79,7 +80,7 @@ pub struct GetCommentsResponse {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CreateCommentReport {
|
pub struct CreateCommentReport {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -108,7 +109,7 @@ pub struct ListCommentReports {
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
/// if no community is given, it returns reports for all communities moderated by the auth user
|
/// if no community is given, it returns reports for all communities moderated by the auth user
|
||||||
pub community: Option<i32>,
|
pub community: Option<CommunityId>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,14 +1,15 @@
|
||||||
|
use lemmy_db_schema::{CommunityId, PersonId};
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_follower_view::CommunityFollowerView,
|
community_follower_view::CommunityFollowerView,
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
user_view::UserViewSafe,
|
person_view::PersonViewSafe,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetCommunity {
|
pub struct GetCommunity {
|
||||||
pub id: Option<i32>,
|
pub id: Option<CommunityId>,
|
||||||
pub name: Option<String>,
|
pub name: Option<String>,
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -27,7 +28,6 @@ pub struct CreateCommunity {
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub category_id: i32,
|
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -53,8 +53,8 @@ pub struct ListCommunitiesResponse {
|
||||||
|
|
||||||
#[derive(Deserialize, Clone)]
|
#[derive(Deserialize, Clone)]
|
||||||
pub struct BanFromCommunity {
|
pub struct BanFromCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub ban: bool,
|
pub ban: bool,
|
||||||
pub remove_data: bool,
|
pub remove_data: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
|
@ -64,14 +64,14 @@ pub struct BanFromCommunity {
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct BanFromCommunityResponse {
|
pub struct BanFromCommunityResponse {
|
||||||
pub user_view: UserViewSafe,
|
pub person_view: PersonViewSafe,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct AddModToCommunity {
|
pub struct AddModToCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub added: bool,
|
pub added: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -83,26 +83,25 @@ pub struct AddModToCommunityResponse {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct EditCommunity {
|
pub struct EditCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<String>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub category_id: i32,
|
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DeleteCommunity {
|
pub struct DeleteCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct RemoveCommunity {
|
pub struct RemoveCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub expires: Option<i64>,
|
pub expires: Option<i64>,
|
||||||
|
@ -111,7 +110,7 @@ pub struct RemoveCommunity {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct FollowCommunity {
|
pub struct FollowCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub follow: bool,
|
pub follow: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -128,7 +127,7 @@ pub struct GetFollowedCommunitiesResponse {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct TransferCommunity {
|
pub struct TransferCommunity {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,22 @@
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod person;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod user;
|
|
||||||
pub mod websocket;
|
pub mod websocket;
|
||||||
|
|
||||||
use diesel::PgConnection;
|
use diesel::PgConnection;
|
||||||
use lemmy_db_queries::{source::user::User, Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
comment::Comment,
|
source::{
|
||||||
post::Post,
|
comment::Comment,
|
||||||
user::User_,
|
person::Person,
|
||||||
user_mention::{UserMention, UserMentionForm},
|
person_mention::{PersonMention, PersonMentionForm},
|
||||||
|
post::Post,
|
||||||
|
},
|
||||||
|
LocalUserId,
|
||||||
};
|
};
|
||||||
|
use lemmy_db_views::local_user_view::LocalUserView;
|
||||||
use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError};
|
use lemmy_utils::{email::send_email, settings::structs::Settings, utils::MentionData, LemmyError};
|
||||||
use log::error;
|
use log::error;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
@ -54,14 +58,13 @@ where
|
||||||
pub async fn send_local_notifs(
|
pub async fn send_local_notifs(
|
||||||
mentions: Vec<MentionData>,
|
mentions: Vec<MentionData>,
|
||||||
comment: Comment,
|
comment: Comment,
|
||||||
user: &User_,
|
person: Person,
|
||||||
post: Post,
|
post: Post,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
do_send_email: bool,
|
do_send_email: bool,
|
||||||
) -> Result<Vec<i32>, LemmyError> {
|
) -> Result<Vec<LocalUserId>, LemmyError> {
|
||||||
let user2 = user.clone();
|
|
||||||
let ids = blocking(pool, move |conn| {
|
let ids = blocking(pool, move |conn| {
|
||||||
do_send_local_notifs(conn, &mentions, &comment, &user2, &post, do_send_email)
|
do_send_local_notifs(conn, &mentions, &comment, &person, &post, do_send_email)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
|
@ -72,40 +75,40 @@ fn do_send_local_notifs(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
mentions: &[MentionData],
|
mentions: &[MentionData],
|
||||||
comment: &Comment,
|
comment: &Comment,
|
||||||
user: &User_,
|
person: &Person,
|
||||||
post: &Post,
|
post: &Post,
|
||||||
do_send_email: bool,
|
do_send_email: bool,
|
||||||
) -> Vec<i32> {
|
) -> Vec<LocalUserId> {
|
||||||
let mut recipient_ids = Vec::new();
|
let mut recipient_ids = Vec::new();
|
||||||
|
|
||||||
// Send the local mentions
|
// Send the local mentions
|
||||||
for mention in mentions
|
for mention in mentions
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|m| m.is_local() && m.name.ne(&user.name))
|
.filter(|m| m.is_local() && m.name.ne(&person.name))
|
||||||
.collect::<Vec<&MentionData>>()
|
.collect::<Vec<&MentionData>>()
|
||||||
{
|
{
|
||||||
if let Ok(mention_user) = User_::read_from_name(&conn, &mention.name) {
|
if let Ok(mention_user_view) = LocalUserView::read_from_name(&conn, &mention.name) {
|
||||||
// TODO
|
// TODO
|
||||||
// At some point, make it so you can't tag the parent creator either
|
// At some point, make it so you can't tag the parent creator either
|
||||||
// This can cause two notifications, one for reply and the other for mention
|
// This can cause two notifications, one for reply and the other for mention
|
||||||
recipient_ids.push(mention_user.id);
|
recipient_ids.push(mention_user_view.local_user.id);
|
||||||
|
|
||||||
let user_mention_form = UserMentionForm {
|
let user_mention_form = PersonMentionForm {
|
||||||
recipient_id: mention_user.id,
|
recipient_id: mention_user_view.person.id,
|
||||||
comment_id: comment.id,
|
comment_id: comment.id,
|
||||||
read: None,
|
read: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Allow this to fail softly, since comment edits might re-update or replace it
|
// Allow this to fail softly, since comment edits might re-update or replace it
|
||||||
// Let the uniqueness handle this fail
|
// Let the uniqueness handle this fail
|
||||||
let _ = UserMention::create(&conn, &user_mention_form);
|
PersonMention::create(&conn, &user_mention_form).ok();
|
||||||
|
|
||||||
// Send an email to those users that have notifications on
|
// Send an email to those local users that have notifications on
|
||||||
if do_send_email && mention_user.send_notifications_to_email {
|
if do_send_email {
|
||||||
send_email_to_user(
|
send_email_to_user(
|
||||||
mention_user,
|
&mention_user_view,
|
||||||
"Mentioned by",
|
"Mentioned by",
|
||||||
"User Mention",
|
"Person Mention",
|
||||||
&comment.content,
|
&comment.content,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -116,12 +119,20 @@ fn do_send_local_notifs(
|
||||||
match comment.parent_id {
|
match comment.parent_id {
|
||||||
Some(parent_id) => {
|
Some(parent_id) => {
|
||||||
if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
|
if let Ok(parent_comment) = Comment::read(&conn, parent_id) {
|
||||||
if parent_comment.creator_id != user.id {
|
// Don't send a notif to yourself
|
||||||
if let Ok(parent_user) = User_::read(&conn, parent_comment.creator_id) {
|
if parent_comment.creator_id != person.id {
|
||||||
recipient_ids.push(parent_user.id);
|
// Get the parent commenter local_user
|
||||||
|
if let Ok(parent_user_view) = LocalUserView::read_person(&conn, parent_comment.creator_id)
|
||||||
|
{
|
||||||
|
recipient_ids.push(parent_user_view.local_user.id);
|
||||||
|
|
||||||
if do_send_email && parent_user.send_notifications_to_email {
|
if do_send_email {
|
||||||
send_email_to_user(parent_user, "Reply from", "Comment Reply", &comment.content)
|
send_email_to_user(
|
||||||
|
&parent_user_view,
|
||||||
|
"Reply from",
|
||||||
|
"Comment Reply",
|
||||||
|
&comment.content,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,12 +140,17 @@ fn do_send_local_notifs(
|
||||||
}
|
}
|
||||||
// Its a post
|
// Its a post
|
||||||
None => {
|
None => {
|
||||||
if post.creator_id != user.id {
|
if post.creator_id != person.id {
|
||||||
if let Ok(parent_user) = User_::read(&conn, post.creator_id) {
|
if let Ok(parent_user_view) = LocalUserView::read_person(&conn, post.creator_id) {
|
||||||
recipient_ids.push(parent_user.id);
|
recipient_ids.push(parent_user_view.local_user.id);
|
||||||
|
|
||||||
if do_send_email && parent_user.send_notifications_to_email {
|
if do_send_email {
|
||||||
send_email_to_user(parent_user, "Reply from", "Post Reply", &comment.content)
|
send_email_to_user(
|
||||||
|
&parent_user_view,
|
||||||
|
"Reply from",
|
||||||
|
"Post Reply",
|
||||||
|
&comment.content,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,26 +159,31 @@ fn do_send_local_notifs(
|
||||||
recipient_ids
|
recipient_ids
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_email_to_user(user: User_, subject_text: &str, body_text: &str, comment_content: &str) {
|
pub fn send_email_to_user(
|
||||||
if user.banned {
|
local_user_view: &LocalUserView,
|
||||||
|
subject_text: &str,
|
||||||
|
body_text: &str,
|
||||||
|
comment_content: &str,
|
||||||
|
) {
|
||||||
|
if local_user_view.person.banned || !local_user_view.local_user.send_notifications_to_email {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(user_email) = user.email {
|
if let Some(user_email) = &local_user_view.local_user.email {
|
||||||
let subject = &format!(
|
let subject = &format!(
|
||||||
"{} - {} {}",
|
"{} - {} {}",
|
||||||
subject_text,
|
subject_text,
|
||||||
Settings::get().hostname(),
|
Settings::get().hostname(),
|
||||||
user.name,
|
local_user_view.person.name,
|
||||||
);
|
);
|
||||||
let html = &format!(
|
let html = &format!(
|
||||||
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
"<h1>{}</h1><br><div>{} - {}</div><br><a href={}/inbox>inbox</a>",
|
||||||
body_text,
|
body_text,
|
||||||
user.name,
|
local_user_view.person.name,
|
||||||
comment_content,
|
comment_content,
|
||||||
Settings::get().get_protocol_and_hostname()
|
Settings::get().get_protocol_and_hostname()
|
||||||
);
|
);
|
||||||
match send_email(subject, &user_email, &user.name, html) {
|
match send_email(subject, &user_email, &local_user_view.person.name, html) {
|
||||||
Ok(_o) => _o,
|
Ok(_o) => _o,
|
||||||
Err(e) => error!("{}", e),
|
Err(e) => error!("{}", e),
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,8 +6,8 @@ use lemmy_db_views::{
|
||||||
use lemmy_db_views_actor::{
|
use lemmy_db_views_actor::{
|
||||||
community_follower_view::CommunityFollowerView,
|
community_follower_view::CommunityFollowerView,
|
||||||
community_moderator_view::CommunityModeratorView,
|
community_moderator_view::CommunityModeratorView,
|
||||||
user_mention_view::UserMentionView,
|
person_mention_view::PersonMentionView,
|
||||||
user_view::UserViewSafe,
|
person_view::PersonViewSafe,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
@ -16,6 +16,7 @@ pub struct Login {
|
||||||
pub username_or_email: String,
|
pub username_or_email: String,
|
||||||
pub password: String,
|
pub password: String,
|
||||||
}
|
}
|
||||||
|
use lemmy_db_schema::{CommunityId, PersonId, PersonMentionId, PrivateMessageId};
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct Register {
|
pub struct Register {
|
||||||
|
@ -45,11 +46,11 @@ pub struct CaptchaResponse {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct SaveUserSettings {
|
pub struct SaveUserSettings {
|
||||||
pub show_nsfw: bool,
|
pub show_nsfw: Option<bool>,
|
||||||
pub theme: String,
|
pub theme: Option<String>,
|
||||||
pub default_sort_type: i16,
|
pub default_sort_type: Option<i16>,
|
||||||
pub default_listing_type: i16,
|
pub default_listing_type: Option<i16>,
|
||||||
pub lang: String,
|
pub lang: Option<String>,
|
||||||
pub avatar: Option<String>,
|
pub avatar: Option<String>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<String>,
|
||||||
pub preferred_username: Option<String>,
|
pub preferred_username: Option<String>,
|
||||||
|
@ -59,8 +60,8 @@ pub struct SaveUserSettings {
|
||||||
pub new_password: Option<String>,
|
pub new_password: Option<String>,
|
||||||
pub new_password_verify: Option<String>,
|
pub new_password_verify: Option<String>,
|
||||||
pub old_password: Option<String>,
|
pub old_password: Option<String>,
|
||||||
pub show_avatars: bool,
|
pub show_avatars: Option<bool>,
|
||||||
pub send_notifications_to_email: bool,
|
pub send_notifications_to_email: Option<bool>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,20 +71,20 @@ pub struct LoginResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetUserDetails {
|
pub struct GetPersonDetails {
|
||||||
pub user_id: Option<i32>,
|
pub person_id: Option<PersonId>,
|
||||||
pub username: Option<String>,
|
pub username: Option<String>,
|
||||||
pub sort: String,
|
pub sort: String,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
pub community_id: Option<i32>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub saved_only: bool,
|
pub saved_only: bool,
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct GetUserDetailsResponse {
|
pub struct GetPersonDetailsResponse {
|
||||||
pub user_view: UserViewSafe,
|
pub person_view: PersonViewSafe,
|
||||||
pub follows: Vec<CommunityFollowerView>,
|
pub follows: Vec<CommunityFollowerView>,
|
||||||
pub moderates: Vec<CommunityModeratorView>,
|
pub moderates: Vec<CommunityModeratorView>,
|
||||||
pub comments: Vec<CommentView>,
|
pub comments: Vec<CommentView>,
|
||||||
|
@ -96,8 +97,8 @@ pub struct GetRepliesResponse {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct GetUserMentionsResponse {
|
pub struct GetPersonMentionsResponse {
|
||||||
pub mentions: Vec<UserMentionView>,
|
pub mentions: Vec<PersonMentionView>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -107,19 +108,19 @@ pub struct MarkAllAsRead {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct AddAdmin {
|
pub struct AddAdmin {
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub added: bool,
|
pub added: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct AddAdminResponse {
|
pub struct AddAdminResponse {
|
||||||
pub admins: Vec<UserViewSafe>,
|
pub admins: Vec<PersonViewSafe>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct BanUser {
|
pub struct BanPerson {
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub ban: bool,
|
pub ban: bool,
|
||||||
pub remove_data: bool,
|
pub remove_data: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
|
@ -128,8 +129,8 @@ pub struct BanUser {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct BanUserResponse {
|
pub struct BanPersonResponse {
|
||||||
pub user_view: UserViewSafe,
|
pub person_view: PersonViewSafe,
|
||||||
pub banned: bool,
|
pub banned: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +144,7 @@ pub struct GetReplies {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetUserMentions {
|
pub struct GetPersonMentions {
|
||||||
pub sort: String,
|
pub sort: String,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
|
@ -152,15 +153,15 @@ pub struct GetUserMentions {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct MarkUserMentionAsRead {
|
pub struct MarkPersonMentionAsRead {
|
||||||
pub user_mention_id: i32,
|
pub person_mention_id: PersonMentionId,
|
||||||
pub read: bool,
|
pub read: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
pub struct UserMentionResponse {
|
pub struct PersonMentionResponse {
|
||||||
pub user_mention_view: UserMentionView,
|
pub person_mention_view: PersonMentionView,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
|
@ -187,27 +188,27 @@ pub struct PasswordChange {
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreatePrivateMessage {
|
pub struct CreatePrivateMessage {
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub recipient_id: i32,
|
pub recipient_id: PersonId,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct EditPrivateMessage {
|
pub struct EditPrivateMessage {
|
||||||
pub private_message_id: i32,
|
pub private_message_id: PrivateMessageId,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DeletePrivateMessage {
|
pub struct DeletePrivateMessage {
|
||||||
pub private_message_id: i32,
|
pub private_message_id: PrivateMessageId,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct MarkPrivateMessageAsRead {
|
pub struct MarkPrivateMessageAsRead {
|
||||||
pub private_message_id: i32,
|
pub private_message_id: PrivateMessageId,
|
||||||
pub read: bool,
|
pub read: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -232,13 +233,13 @@ pub struct PrivateMessageResponse {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
pub struct GetReportCount {
|
pub struct GetReportCount {
|
||||||
pub community: Option<i32>,
|
pub community: Option<CommunityId>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Clone, Debug)]
|
#[derive(Serialize, Deserialize, Clone, Debug)]
|
||||||
pub struct GetReportCountResponse {
|
pub struct GetReportCountResponse {
|
||||||
pub community: Option<i32>,
|
pub community: Option<CommunityId>,
|
||||||
pub comment_reports: i64,
|
pub comment_reports: i64,
|
||||||
pub post_reports: i64,
|
pub post_reports: i64,
|
||||||
}
|
}
|
|
@ -1,3 +1,4 @@
|
||||||
|
use lemmy_db_schema::{CommunityId, PostId};
|
||||||
use lemmy_db_views::{
|
use lemmy_db_views::{
|
||||||
comment_view::CommentView,
|
comment_view::CommentView,
|
||||||
post_report_view::PostReportView,
|
post_report_view::PostReportView,
|
||||||
|
@ -8,14 +9,15 @@ use lemmy_db_views_actor::{
|
||||||
community_view::CommunityView,
|
community_view::CommunityView,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct CreatePost {
|
pub struct CreatePost {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<Url>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,7 +28,7 @@ pub struct PostResponse {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetPost {
|
pub struct GetPost {
|
||||||
pub id: i32,
|
pub id: PostId,
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,7 +47,7 @@ pub struct GetPosts {
|
||||||
pub sort: String,
|
pub sort: String,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
pub community_id: Option<i32>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub community_name: Option<String>,
|
pub community_name: Option<String>,
|
||||||
pub auth: Option<String>,
|
pub auth: Option<String>,
|
||||||
}
|
}
|
||||||
|
@ -57,16 +59,16 @@ pub struct GetPostsResponse {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct CreatePostLike {
|
pub struct CreatePostLike {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct EditPost {
|
pub struct EditPost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub url: Option<String>,
|
pub url: Option<Url>,
|
||||||
pub body: Option<String>,
|
pub body: Option<String>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
@ -74,14 +76,14 @@ pub struct EditPost {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct DeletePost {
|
pub struct DeletePost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct RemovePost {
|
pub struct RemovePost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
|
@ -89,28 +91,28 @@ pub struct RemovePost {
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct LockPost {
|
pub struct LockPost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub locked: bool,
|
pub locked: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct StickyPost {
|
pub struct StickyPost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub stickied: bool,
|
pub stickied: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct SavePost {
|
pub struct SavePost {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub save: bool,
|
pub save: bool,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct CreatePostReport {
|
pub struct CreatePostReport {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
@ -137,7 +139,7 @@ pub struct ResolvePostReportResponse {
|
||||||
pub struct ListPostReports {
|
pub struct ListPostReports {
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
pub community: Option<i32>,
|
pub community: Option<CommunityId>,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
use lemmy_db_schema::source::user::UserSafeSettings;
|
use lemmy_db_schema::{CommunityId, PersonId};
|
||||||
use lemmy_db_views::{comment_view::CommentView, post_view::PostView, site_view::SiteView};
|
use lemmy_db_views::{
|
||||||
use lemmy_db_views_actor::{community_view::CommunityView, user_view::UserViewSafe};
|
comment_view::CommentView,
|
||||||
|
local_user_view::LocalUserSettingsView,
|
||||||
|
post_view::PostView,
|
||||||
|
site_view::SiteView,
|
||||||
|
};
|
||||||
|
use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};
|
||||||
use lemmy_db_views_moderator::{
|
use lemmy_db_views_moderator::{
|
||||||
mod_add_community_view::ModAddCommunityView,
|
mod_add_community_view::ModAddCommunityView,
|
||||||
mod_add_view::ModAddView,
|
mod_add_view::ModAddView,
|
||||||
|
@ -13,12 +18,13 @@ use lemmy_db_views_moderator::{
|
||||||
mod_sticky_post_view::ModStickyPostView,
|
mod_sticky_post_view::ModStickyPostView,
|
||||||
};
|
};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct Search {
|
pub struct Search {
|
||||||
pub q: String,
|
pub q: String,
|
||||||
pub type_: String,
|
pub type_: String,
|
||||||
pub community_id: Option<i32>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub community_name: Option<String>,
|
pub community_name: Option<String>,
|
||||||
pub sort: String,
|
pub sort: String,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
|
@ -32,13 +38,13 @@ pub struct SearchResponse {
|
||||||
pub comments: Vec<CommentView>,
|
pub comments: Vec<CommentView>,
|
||||||
pub posts: Vec<PostView>,
|
pub posts: Vec<PostView>,
|
||||||
pub communities: Vec<CommunityView>,
|
pub communities: Vec<CommunityView>,
|
||||||
pub users: Vec<UserViewSafe>,
|
pub users: Vec<PersonViewSafe>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct GetModlog {
|
pub struct GetModlog {
|
||||||
pub mod_user_id: Option<i32>,
|
pub mod_person_id: Option<PersonId>,
|
||||||
pub community_id: Option<i32>,
|
pub community_id: Option<CommunityId>,
|
||||||
pub page: Option<i64>,
|
pub page: Option<i64>,
|
||||||
pub limit: Option<i64>,
|
pub limit: Option<i64>,
|
||||||
}
|
}
|
||||||
|
@ -60,8 +66,8 @@ pub struct GetModlogResponse {
|
||||||
pub struct CreateSite {
|
pub struct CreateSite {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<Url>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<Url>,
|
||||||
pub enable_downvotes: bool,
|
pub enable_downvotes: bool,
|
||||||
pub open_registration: bool,
|
pub open_registration: bool,
|
||||||
pub enable_nsfw: bool,
|
pub enable_nsfw: bool,
|
||||||
|
@ -93,17 +99,17 @@ pub struct SiteResponse {
|
||||||
#[derive(Serialize)]
|
#[derive(Serialize)]
|
||||||
pub struct GetSiteResponse {
|
pub struct GetSiteResponse {
|
||||||
pub site_view: Option<SiteView>, // Because the site might not be set up yet
|
pub site_view: Option<SiteView>, // Because the site might not be set up yet
|
||||||
pub admins: Vec<UserViewSafe>,
|
pub admins: Vec<PersonViewSafe>,
|
||||||
pub banned: Vec<UserViewSafe>,
|
pub banned: Vec<PersonViewSafe>,
|
||||||
pub online: usize,
|
pub online: usize,
|
||||||
pub version: String,
|
pub version: String,
|
||||||
pub my_user: Option<UserSafeSettings>,
|
pub my_user: Option<LocalUserSettingsView>,
|
||||||
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
|
pub federated_instances: Option<FederatedInstances>, // Federation may be disabled
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct TransferSite {
|
pub struct TransferSite {
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub auth: String,
|
pub auth: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
use lemmy_db_schema::{CommunityId, PostId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
|
@ -12,7 +13,7 @@ pub struct UserJoinResponse {
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct CommunityJoin {
|
pub struct CommunityJoin {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
|
@ -22,7 +23,7 @@ pub struct CommunityJoinResponse {
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct ModJoin {
|
pub struct ModJoin {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
|
@ -32,7 +33,7 @@ pub struct ModJoinResponse {
|
||||||
|
|
||||||
#[derive(Deserialize, Debug)]
|
#[derive(Deserialize, Debug)]
|
||||||
pub struct PostJoin {
|
pub struct PostJoin {
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Serialize, Clone)]
|
#[derive(Serialize, Clone)]
|
||||||
|
|
|
@ -32,7 +32,7 @@ rand = "0.8.3"
|
||||||
strum = "0.20.0"
|
strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
percent-encoding = "2.1.0"
|
percent-encoding = "2.1.0"
|
||||||
openssl = "0.10.32"
|
openssl = "0.10.32"
|
||||||
http = "0.2.3"
|
http = "0.2.3"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{activities::receive::get_actor_as_user, objects::FromApub, ActorType, NoteExt};
|
use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, NoteExt};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{ActorAndObjectRefExt, Create, Dislike, Like, Remove, Update},
|
activity::{ActorAndObjectRefExt, Create, Dislike, Like, Remove, Update},
|
||||||
base::ExtendsExt,
|
base::ExtendsExt,
|
||||||
|
@ -19,11 +19,11 @@ pub(crate) async fn receive_create_comment(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&create, context, request_counter).await?;
|
let person = get_actor_as_person(&create, context, request_counter).await?;
|
||||||
let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
|
let note = NoteExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let comment = Comment::from_apub(¬e, context, user.actor_id(), request_counter).await?;
|
let comment = Comment::from_apub(¬e, context, person.actor_id(), request_counter).await?;
|
||||||
|
|
||||||
let post_id = comment.post_id;
|
let post_id = comment.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
@ -33,8 +33,15 @@ pub(crate) async fn receive_create_comment(
|
||||||
// Its much easier to scrape them from the comment body, since the API has to do that
|
// Its much easier to scrape them from the comment body, since the API has to do that
|
||||||
// anyway.
|
// anyway.
|
||||||
let mentions = scrape_text_for_mentions(&comment.content);
|
let mentions = scrape_text_for_mentions(&comment.content);
|
||||||
let recipient_ids =
|
let recipient_ids = send_local_notifs(
|
||||||
send_local_notifs(mentions, comment.clone(), &user, post, context.pool(), true).await?;
|
mentions,
|
||||||
|
comment.clone(),
|
||||||
|
person,
|
||||||
|
post,
|
||||||
|
context.pool(),
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
|
@ -64,9 +71,9 @@ pub(crate) async fn receive_update_comment(
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let note = NoteExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
|
let note = NoteExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let user = get_actor_as_user(&update, context, request_counter).await?;
|
let person = get_actor_as_person(&update, context, request_counter).await?;
|
||||||
|
|
||||||
let comment = Comment::from_apub(¬e, context, user.actor_id(), request_counter).await?;
|
let comment = Comment::from_apub(¬e, context, person.actor_id(), request_counter).await?;
|
||||||
|
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
let post_id = comment.post_id;
|
let post_id = comment.post_id;
|
||||||
|
@ -74,7 +81,7 @@ pub(crate) async fn receive_update_comment(
|
||||||
|
|
||||||
let mentions = scrape_text_for_mentions(&comment.content);
|
let mentions = scrape_text_for_mentions(&comment.content);
|
||||||
let recipient_ids =
|
let recipient_ids =
|
||||||
send_local_notifs(mentions, comment, &user, post, context.pool(), false).await?;
|
send_local_notifs(mentions, comment, person, post, context.pool(), false).await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let comment_view = blocking(context.pool(), move |conn| {
|
let comment_view = blocking(context.pool(), move |conn| {
|
||||||
|
@ -103,18 +110,18 @@ pub(crate) async fn receive_like_comment(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&like, context, request_counter).await?;
|
let person = get_actor_as_person(&like, context, request_counter).await?;
|
||||||
|
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id,
|
comment_id,
|
||||||
post_id: comment.post_id,
|
post_id: comment.post_id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
CommentLike::remove(conn, user_id, comment_id)?;
|
CommentLike::remove(conn, person_id, comment_id)?;
|
||||||
CommentLike::like(conn, &like_form)
|
CommentLike::like(conn, &like_form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
@ -148,18 +155,18 @@ pub(crate) async fn receive_dislike_comment(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&dislike, context, request_counter).await?;
|
let person = get_actor_as_person(&dislike, context, request_counter).await?;
|
||||||
|
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
let like_form = CommentLikeForm {
|
let like_form = CommentLikeForm {
|
||||||
comment_id,
|
comment_id,
|
||||||
post_id: comment.post_id,
|
post_id: comment.post_id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
score: -1,
|
score: -1,
|
||||||
};
|
};
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
CommentLike::remove(conn, user_id, comment_id)?;
|
CommentLike::remove(conn, person_id, comment_id)?;
|
||||||
CommentLike::like(conn, &like_form)
|
CommentLike::like(conn, &like_form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::activities::receive::get_actor_as_user;
|
use crate::activities::receive::get_actor_as_person;
|
||||||
use activitystreams::activity::{Dislike, Like};
|
use activitystreams::activity::{Dislike, Like};
|
||||||
use lemmy_api_structs::{blocking, comment::CommentResponse};
|
use lemmy_api_structs::{blocking, comment::CommentResponse};
|
||||||
use lemmy_db_queries::{source::comment::Comment_, Likeable};
|
use lemmy_db_queries::{source::comment::Comment_, Likeable};
|
||||||
|
@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_comment(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(like, context, request_counter).await?;
|
let person = get_actor_as_person(like, context, request_counter).await?;
|
||||||
|
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
CommentLike::remove(conn, user_id, comment_id)
|
CommentLike::remove(conn, person_id, comment_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -51,12 +51,12 @@ pub(crate) async fn receive_undo_dislike_comment(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(dislike, context, request_counter).await?;
|
let person = get_actor_as_person(dislike, context, request_counter).await?;
|
||||||
|
|
||||||
let comment_id = comment.id;
|
let comment_id = comment.id;
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
CommentLike::remove(conn, user_id, comment_id)
|
CommentLike::remove(conn, person_id, comment_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::fetcher::user::get_or_fetch_and_upsert_user;
|
use crate::fetcher::person::get_or_fetch_and_upsert_person;
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{ActorAndObjectRef, ActorAndObjectRefExt},
|
activity::{ActorAndObjectRef, ActorAndObjectRefExt},
|
||||||
base::{AsBase, BaseExt},
|
base::{AsBase, BaseExt},
|
||||||
error::DomainError,
|
error::DomainError,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use lemmy_db_schema::source::user::User_;
|
use lemmy_db_schema::source::person::Person;
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -28,18 +28,18 @@ where
|
||||||
Err(anyhow!("Activity not supported").into())
|
Err(anyhow!("Activity not supported").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reads the actor field of an activity and returns the corresponding `User_`.
|
/// Reads the actor field of an activity and returns the corresponding `Person`.
|
||||||
pub(crate) async fn get_actor_as_user<T, A>(
|
pub(crate) async fn get_actor_as_person<T, A>(
|
||||||
activity: &T,
|
activity: &T,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<User_, LemmyError>
|
) -> Result<Person, LemmyError>
|
||||||
where
|
where
|
||||||
T: AsBase<A> + ActorAndObjectRef,
|
T: AsBase<A> + ActorAndObjectRef,
|
||||||
{
|
{
|
||||||
let actor = activity.actor()?;
|
let actor = activity.actor()?;
|
||||||
let user_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
|
let person_uri = actor.as_single_xsd_any_uri().context(location_info!())?;
|
||||||
get_or_fetch_and_upsert_user(&user_uri, context, request_counter).await
|
get_or_fetch_and_upsert_person(&person_uri, context, request_counter).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Ensure that the ID of an incoming activity comes from the same domain as the actor. Optionally
|
/// Ensure that the ID of an incoming activity comes from the same domain as the actor. Optionally
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{activities::receive::get_actor_as_user, objects::FromApub, ActorType, PageExt};
|
use crate::{activities::receive::get_actor_as_person, objects::FromApub, ActorType, PageExt};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
activity::{Create, Dislike, Like, Remove, Update},
|
activity::{Create, Dislike, Like, Remove, Update},
|
||||||
prelude::*,
|
prelude::*,
|
||||||
|
@ -16,11 +16,11 @@ pub(crate) async fn receive_create_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&create, context, request_counter).await?;
|
let person = get_actor_as_person(&create, context, request_counter).await?;
|
||||||
let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
|
let page = PageExt::from_any_base(create.object().to_owned().one().context(location_info!())?)?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?;
|
let post = Post::from_apub(&page, context, person.actor_id(), request_counter).await?;
|
||||||
|
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
|
@ -45,11 +45,11 @@ pub(crate) async fn receive_update_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&update, context, request_counter).await?;
|
let person = get_actor_as_person(&update, context, request_counter).await?;
|
||||||
let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
|
let page = PageExt::from_any_base(update.object().to_owned().one().context(location_info!())?)?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let post = Post::from_apub(&page, context, user.actor_id(), request_counter).await?;
|
let post = Post::from_apub(&page, context, person.actor_id(), request_counter).await?;
|
||||||
|
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
// Refetch the view
|
// Refetch the view
|
||||||
|
@ -75,17 +75,17 @@ pub(crate) async fn receive_like_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&like, context, request_counter).await?;
|
let person = get_actor_as_person(&like, context, request_counter).await?;
|
||||||
|
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
let like_form = PostLikeForm {
|
let like_form = PostLikeForm {
|
||||||
post_id,
|
post_id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
PostLike::remove(conn, user_id, post_id)?;
|
PostLike::remove(conn, person_id, post_id)?;
|
||||||
PostLike::like(conn, &like_form)
|
PostLike::like(conn, &like_form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
@ -113,17 +113,17 @@ pub(crate) async fn receive_dislike_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(&dislike, context, request_counter).await?;
|
let person = get_actor_as_person(&dislike, context, request_counter).await?;
|
||||||
|
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
let like_form = PostLikeForm {
|
let like_form = PostLikeForm {
|
||||||
post_id,
|
post_id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
score: -1,
|
score: -1,
|
||||||
};
|
};
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
PostLike::remove(conn, user_id, post_id)?;
|
PostLike::remove(conn, person_id, post_id)?;
|
||||||
PostLike::like(conn, &like_form)
|
PostLike::like(conn, &like_form)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::activities::receive::get_actor_as_user;
|
use crate::activities::receive::get_actor_as_person;
|
||||||
use activitystreams::activity::{Dislike, Like};
|
use activitystreams::activity::{Dislike, Like};
|
||||||
use lemmy_api_structs::{blocking, post::PostResponse};
|
use lemmy_api_structs::{blocking, post::PostResponse};
|
||||||
use lemmy_db_queries::{source::post::Post_, Likeable};
|
use lemmy_db_queries::{source::post::Post_, Likeable};
|
||||||
|
@ -13,12 +13,12 @@ pub(crate) async fn receive_undo_like_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(like, context, request_counter).await?;
|
let person = get_actor_as_person(like, context, request_counter).await?;
|
||||||
|
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
PostLike::remove(conn, user_id, post_id)
|
PostLike::remove(conn, person_id, post_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ pub(crate) async fn receive_undo_dislike_post(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let user = get_actor_as_user(dislike, context, request_counter).await?;
|
let person = get_actor_as_person(dislike, context, request_counter).await?;
|
||||||
|
|
||||||
let post_id = post.id;
|
let post_id = post.id;
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
PostLike::remove(conn, user_id, post_id)
|
PostLike::remove(conn, person_id, post_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
activities::receive::verify_activity_domains_valid,
|
activities::receive::verify_activity_domains_valid,
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
inbox::get_activity_to_and_cc,
|
inbox::get_activity_to_and_cc,
|
||||||
objects::FromApub,
|
objects::FromApub,
|
||||||
NoteExt,
|
NoteExt,
|
||||||
|
@ -13,10 +13,10 @@ use activitystreams::{
|
||||||
public,
|
public,
|
||||||
};
|
};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use lemmy_api_structs::{blocking, user::PrivateMessageResponse};
|
use lemmy_api_structs::{blocking, person::PrivateMessageResponse};
|
||||||
use lemmy_db_queries::source::private_message::PrivateMessage_;
|
use lemmy_db_queries::source::private_message::PrivateMessage_;
|
||||||
use lemmy_db_schema::source::private_message::PrivateMessage;
|
use lemmy_db_schema::source::private_message::PrivateMessage;
|
||||||
use lemmy_db_views::private_message_view::PrivateMessageView;
|
use lemmy_db_views::{local_user_view::LocalUserView, private_message_view::PrivateMessageView};
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
|
use lemmy_websocket::{messages::SendUserRoomMessage, LemmyContext, UserOperation};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -50,12 +50,19 @@ pub(crate) async fn receive_create_private_message(
|
||||||
private_message_view: message,
|
private_message_view: message,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Send notifications to the local recipient, if one exists
|
||||||
let recipient_id = res.private_message_view.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
let local_recipient_id = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.local_user
|
||||||
|
.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::CreatePrivateMessage,
|
op: UserOperation::CreatePrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
recipient_id,
|
local_recipient_id,
|
||||||
websocket_id: None,
|
websocket_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -91,11 +98,17 @@ pub(crate) async fn receive_update_private_message(
|
||||||
};
|
};
|
||||||
|
|
||||||
let recipient_id = res.private_message_view.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
let local_recipient_id = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.local_user
|
||||||
|
.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
recipient_id,
|
local_recipient_id,
|
||||||
websocket_id: None,
|
websocket_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -123,11 +136,19 @@ pub(crate) async fn receive_delete_private_message(
|
||||||
let res = PrivateMessageResponse {
|
let res = PrivateMessageResponse {
|
||||||
private_message_view: message,
|
private_message_view: message,
|
||||||
};
|
};
|
||||||
|
|
||||||
let recipient_id = res.private_message_view.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
let local_recipient_id = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.local_user
|
||||||
|
.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
recipient_id,
|
local_recipient_id,
|
||||||
websocket_id: None,
|
websocket_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -160,11 +181,19 @@ pub(crate) async fn receive_undo_delete_private_message(
|
||||||
let res = PrivateMessageResponse {
|
let res = PrivateMessageResponse {
|
||||||
private_message_view: message,
|
private_message_view: message,
|
||||||
};
|
};
|
||||||
|
|
||||||
let recipient_id = res.private_message_view.recipient.id;
|
let recipient_id = res.private_message_view.recipient.id;
|
||||||
|
let local_recipient_id = blocking(context.pool(), move |conn| {
|
||||||
|
LocalUserView::read_person(conn, recipient_id)
|
||||||
|
})
|
||||||
|
.await??
|
||||||
|
.local_user
|
||||||
|
.id;
|
||||||
|
|
||||||
context.chat_server().do_send(SendUserRoomMessage {
|
context.chat_server().do_send(SendUserRoomMessage {
|
||||||
op: UserOperation::EditPrivateMessage,
|
op: UserOperation::EditPrivateMessage,
|
||||||
response: res,
|
response: res,
|
||||||
recipient_id,
|
local_recipient_id,
|
||||||
websocket_id: None,
|
websocket_id: None,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -181,19 +210,19 @@ where
|
||||||
{
|
{
|
||||||
let to_and_cc = get_activity_to_and_cc(activity);
|
let to_and_cc = get_activity_to_and_cc(activity);
|
||||||
if to_and_cc.len() != 1 {
|
if to_and_cc.len() != 1 {
|
||||||
return Err(anyhow!("Private message can only be addressed to one user").into());
|
return Err(anyhow!("Private message can only be addressed to one person").into());
|
||||||
}
|
}
|
||||||
if to_and_cc.contains(&public()) {
|
if to_and_cc.contains(&public()) {
|
||||||
return Err(anyhow!("Private message cant be public").into());
|
return Err(anyhow!("Private message cant be public").into());
|
||||||
}
|
}
|
||||||
let user_id = activity
|
let person_id = activity
|
||||||
.actor()?
|
.actor()?
|
||||||
.to_owned()
|
.to_owned()
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
check_is_apub_id_valid(&user_id)?;
|
check_is_apub_id_valid(&person_id)?;
|
||||||
// check that the sender is a user, not a community
|
// check that the sender is a person, not a community
|
||||||
get_or_fetch_and_upsert_user(&user_id, &context, request_counter).await?;
|
get_or_fetch_and_upsert_person(&person_id, &context, request_counter).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
activities::send::generate_activity_id,
|
activities::send::generate_activity_id,
|
||||||
activity_queue::{send_comment_mentions, send_to_community},
|
activity_queue::{send_comment_mentions, send_to_community},
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
objects::ToApub,
|
objects::ToApub,
|
||||||
ActorType,
|
ActorType,
|
||||||
ApubLikeableType,
|
ApubLikeableType,
|
||||||
|
@ -28,7 +28,7 @@ use anyhow::anyhow;
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_api_structs::{blocking, WebFingerResponse};
|
use lemmy_api_structs::{blocking, WebFingerResponse};
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{comment::Comment, community::Community, post::Post, user::User_};
|
use lemmy_db_schema::source::{comment::Comment, community::Community, person::Person, post::Post};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
request::{retry, RecvError},
|
request::{retry, RecvError},
|
||||||
settings::structs::Settings,
|
settings::structs::Settings,
|
||||||
|
@ -44,8 +44,8 @@ use url::Url;
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubObjectType for Comment {
|
impl ApubObjectType for Comment {
|
||||||
/// Send out information about a newly created comment, to the followers of the community and
|
/// Send out information about a newly created comment, to the followers of the community and
|
||||||
/// mentioned users.
|
/// mentioned persons.
|
||||||
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let note = self.to_apub(context.pool()).await?;
|
let note = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
|
@ -77,8 +77,8 @@ impl ApubObjectType for Comment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send out information about an edited post, to the followers of the community and mentioned
|
/// Send out information about an edited post, to the followers of the community and mentioned
|
||||||
/// users.
|
/// persons.
|
||||||
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let note = self.to_apub(context.pool()).await?;
|
let note = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
|
@ -109,7 +109,7 @@ impl ApubObjectType for Comment {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ impl ApubObjectType for Comment {
|
||||||
|
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
|
@ -173,7 +173,7 @@ impl ApubObjectType for Comment {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
|
@ -197,7 +197,11 @@ impl ApubObjectType for Comment {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_undo_remove(
|
||||||
|
&self,
|
||||||
|
mod_: &Person,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
|
@ -236,7 +240,7 @@ impl ApubObjectType for Comment {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubLikeableType for Comment {
|
impl ApubLikeableType for Comment {
|
||||||
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_like(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
|
@ -260,7 +264,7 @@ impl ApubLikeableType for Comment {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_dislike(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
|
||||||
|
@ -286,7 +290,7 @@ impl ApubLikeableType for Comment {
|
||||||
|
|
||||||
async fn send_undo_like(
|
async fn send_undo_like(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
|
@ -342,7 +346,7 @@ impl MentionsAndAddresses {
|
||||||
|
|
||||||
/// This takes a comment, and builds a list of to_addresses, inboxes,
|
/// This takes a comment, and builds a list of to_addresses, inboxes,
|
||||||
/// and mention tags, so they know where to be sent to.
|
/// and mention tags, so they know where to be sent to.
|
||||||
/// Addresses are the users / addresses that go in the cc field.
|
/// Addresses are the persons / addresses that go in the cc field.
|
||||||
async fn collect_non_local_mentions(
|
async fn collect_non_local_mentions(
|
||||||
comment: &Comment,
|
comment: &Comment,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
|
@ -356,7 +360,7 @@ async fn collect_non_local_mentions(
|
||||||
// Add the mention tag
|
// Add the mention tag
|
||||||
let mut tags = Vec::new();
|
let mut tags = Vec::new();
|
||||||
|
|
||||||
// Get the user IDs for any mentions
|
// Get the person IDs for any mentions
|
||||||
let mentions = scrape_text_for_mentions(&comment.content)
|
let mentions = scrape_text_for_mentions(&comment.content)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
// Filter only the non-local ones
|
// Filter only the non-local ones
|
||||||
|
@ -369,8 +373,8 @@ async fn collect_non_local_mentions(
|
||||||
debug!("mention actor_id: {}", actor_id);
|
debug!("mention actor_id: {}", actor_id);
|
||||||
addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
|
addressed_ccs.push(actor_id.to_owned().to_string().parse()?);
|
||||||
|
|
||||||
let mention_user = get_or_fetch_and_upsert_user(&actor_id, context, &mut 0).await?;
|
let mention_person = get_or_fetch_and_upsert_person(&actor_id, context, &mut 0).await?;
|
||||||
inboxes.push(mention_user.get_shared_inbox_or_inbox_url());
|
inboxes.push(mention_person.get_shared_inbox_or_inbox_url());
|
||||||
|
|
||||||
let mut mention_tag = Mention::new();
|
let mut mention_tag = Mention::new();
|
||||||
mention_tag.set_href(actor_id).set_name(mention.full_name());
|
mention_tag.set_href(actor_id).set_name(mention.full_name());
|
||||||
|
@ -387,9 +391,12 @@ async fn collect_non_local_mentions(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the apub ID of the user this comment is responding to. Meaning, in case this is a
|
/// Returns the apub ID of the person this comment is responding to. Meaning, in case this is a
|
||||||
/// top-level comment, the creator of the post, otherwise the creator of the parent comment.
|
/// top-level comment, the creator of the post, otherwise the creator of the parent comment.
|
||||||
async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result<User_, LemmyError> {
|
async fn get_comment_parent_creator(
|
||||||
|
pool: &DbPool,
|
||||||
|
comment: &Comment,
|
||||||
|
) -> Result<Person, LemmyError> {
|
||||||
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
|
let parent_creator_id = if let Some(parent_comment_id) = comment.parent_id {
|
||||||
let parent_comment =
|
let parent_comment =
|
||||||
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
|
blocking(pool, move |conn| Comment::read(conn, parent_comment_id)).await??;
|
||||||
|
@ -399,10 +406,10 @@ async fn get_comment_parent_creator(pool: &DbPool, comment: &Comment) -> Result<
|
||||||
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
let parent_post = blocking(pool, move |conn| Post::read(conn, parent_post_id)).await??;
|
||||||
parent_post.creator_id
|
parent_post.creator_id
|
||||||
};
|
};
|
||||||
Ok(blocking(pool, move |conn| User_::read(conn, parent_creator_id)).await??)
|
Ok(blocking(pool, move |conn| Person::read(conn, parent_creator_id)).await??)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Turns a user id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
/// Turns a person id like `@name@example.com` into an apub ID, like `https://example.com/user/name`,
|
||||||
/// using webfinger.
|
/// using webfinger.
|
||||||
async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result<Url, LemmyError> {
|
async fn fetch_webfinger_url(mention: &MentionData, client: &Client) -> Result<Url, LemmyError> {
|
||||||
let fetch_url = format!(
|
let fetch_url = format!(
|
||||||
|
|
|
@ -3,7 +3,8 @@ use crate::{
|
||||||
activity_queue::{send_activity_single_dest, send_to_community_followers},
|
activity_queue::{send_activity_single_dest, send_to_community_followers},
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
|
insert_activity,
|
||||||
ActorType,
|
ActorType,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -27,7 +28,7 @@ use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::DbPool;
|
use lemmy_db_queries::DbPool;
|
||||||
use lemmy_db_schema::source::community::Community;
|
use lemmy_db_schema::source::community::Community;
|
||||||
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
use lemmy_db_views_actor::community_follower_view::CommunityFollowerView;
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ impl ActorType for Community {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As a local community, accept the follow request from a remote user.
|
/// As a local community, accept the follow request from a remote person.
|
||||||
async fn send_accept_follow(
|
async fn send_accept_follow(
|
||||||
&self,
|
&self,
|
||||||
follow: Follow,
|
follow: Follow,
|
||||||
|
@ -80,7 +81,7 @@ impl ActorType for Community {
|
||||||
.actor()?
|
.actor()?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let user = get_or_fetch_and_upsert_user(actor_uri, context, &mut 0).await?;
|
let person = get_or_fetch_and_upsert_person(actor_uri, context, &mut 0).await?;
|
||||||
|
|
||||||
let mut accept = Accept::new(
|
let mut accept = Accept::new(
|
||||||
self.actor_id.to_owned().into_inner(),
|
self.actor_id.to_owned().into_inner(),
|
||||||
|
@ -89,9 +90,9 @@ impl ActorType for Community {
|
||||||
accept
|
accept
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(generate_activity_id(AcceptType::Accept)?)
|
.set_id(generate_activity_id(AcceptType::Accept)?)
|
||||||
.set_to(user.actor_id());
|
.set_to(person.actor_id());
|
||||||
|
|
||||||
send_activity_single_dest(accept, self, user.inbox_url.into(), context).await?;
|
send_activity_single_dest(accept, self, person.inbox_url.into(), context).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,11 +165,20 @@ impl ActorType for Community {
|
||||||
|
|
||||||
/// Wraps an activity sent to the community in an announce, and then sends the announce to all
|
/// Wraps an activity sent to the community in an announce, and then sends the announce to all
|
||||||
/// community followers.
|
/// community followers.
|
||||||
|
///
|
||||||
|
/// If we are announcing a local activity, it hasn't been stored in the database yet, and we need
|
||||||
|
/// to do it here, so that it can be fetched by ID. Remote activities are inserted into DB in the
|
||||||
|
/// inbox.
|
||||||
async fn send_announce(
|
async fn send_announce(
|
||||||
&self,
|
&self,
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
|
let inner_id = activity.id().context(location_info!())?;
|
||||||
|
if inner_id.domain() == Some(&Settings::get().get_hostname_without_port()?) {
|
||||||
|
insert_activity(inner_id, activity.clone(), true, false, context.pool()).await?;
|
||||||
|
}
|
||||||
|
|
||||||
let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity);
|
let mut announce = Announce::new(self.actor_id.to_owned().into_inner(), activity);
|
||||||
announce
|
announce
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
|
|
|
@ -4,9 +4,9 @@ use uuid::Uuid;
|
||||||
|
|
||||||
pub(crate) mod comment;
|
pub(crate) mod comment;
|
||||||
pub(crate) mod community;
|
pub(crate) mod community;
|
||||||
|
pub(crate) mod person;
|
||||||
pub(crate) mod post;
|
pub(crate) mod post;
|
||||||
pub(crate) mod private_message;
|
pub(crate) mod private_message;
|
||||||
pub(crate) mod user;
|
|
||||||
|
|
||||||
/// Generate a unique ID for an activity, in the format:
|
/// Generate a unique ID for an activity, in the format:
|
||||||
/// `http(s)://example.com/receive/create/202daf0a-1489-45df-8d2e-c8a3173fed36`
|
/// `http(s)://example.com/receive/create/202daf0a-1489-45df-8d2e-c8a3173fed36`
|
||||||
|
|
|
@ -17,14 +17,14 @@ use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{ApubObject, DbPool, Followable};
|
use lemmy_db_queries::{ApubObject, DbPool, Followable};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm},
|
community::{Community, CommunityFollower, CommunityFollowerForm},
|
||||||
user::User_,
|
person::Person,
|
||||||
};
|
};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ActorType for User_ {
|
impl ActorType for Person {
|
||||||
fn is_local(&self) -> bool {
|
fn is_local(&self) -> bool {
|
||||||
self.local
|
self.local
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ impl ActorType for User_ {
|
||||||
.into()
|
.into()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// As a given local user, send out a follow request to a remote community.
|
/// As a given local person, send out a follow request to a remote community.
|
||||||
async fn send_follow(
|
async fn send_follow(
|
||||||
&self,
|
&self,
|
||||||
follow_actor_id: &Url,
|
follow_actor_id: &Url,
|
||||||
|
@ -62,7 +62,7 @@ impl ActorType for User_ {
|
||||||
|
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
user_id: self.id,
|
person_id: self.id,
|
||||||
pending: true,
|
pending: true,
|
||||||
};
|
};
|
||||||
blocking(&context.pool(), move |conn| {
|
blocking(&context.pool(), move |conn| {
|
|
@ -23,14 +23,14 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::{community::Community, post::Post, user::User_};
|
use lemmy_db_schema::source::{community::Community, person::Person, post::Post};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubObjectType for Post {
|
impl ApubObjectType for Post {
|
||||||
/// Send out information about a newly created post, to the followers of the community.
|
/// Send out information about a newly created post, to the followers of the community.
|
||||||
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let page = self.to_apub(context.pool()).await?;
|
let page = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
|
@ -54,7 +54,7 @@ impl ApubObjectType for Post {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send out information about an edited post, to the followers of the community.
|
/// Send out information about an edited post, to the followers of the community.
|
||||||
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let page = self.to_apub(context.pool()).await?;
|
let page = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
|
@ -77,7 +77,7 @@ impl ApubObjectType for Post {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -100,7 +100,7 @@ impl ApubObjectType for Post {
|
||||||
|
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
|
@ -134,7 +134,7 @@ impl ApubObjectType for Post {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_remove(&self, mod_: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -155,7 +155,11 @@ impl ApubObjectType for Post {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_undo_remove(
|
||||||
|
&self,
|
||||||
|
mod_: &Person,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -190,7 +194,7 @@ impl ApubObjectType for Post {
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubLikeableType for Post {
|
impl ApubLikeableType for Post {
|
||||||
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_like(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -211,7 +215,7 @@ impl ApubLikeableType for Post {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_dislike(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(context.pool(), move |conn| {
|
let community = blocking(context.pool(), move |conn| {
|
||||||
Community::read(conn, community_id)
|
Community::read(conn, community_id)
|
||||||
|
@ -234,7 +238,7 @@ impl ApubLikeableType for Post {
|
||||||
|
|
||||||
async fn send_undo_like(
|
async fn send_undo_like(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
|
|
|
@ -18,18 +18,19 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::{private_message::PrivateMessage, user::User_};
|
use lemmy_db_schema::source::{person::Person, private_message::PrivateMessage};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ApubObjectType for PrivateMessage {
|
impl ApubObjectType for PrivateMessage {
|
||||||
/// Send out information about a newly created private message
|
/// Send out information about a newly created private message
|
||||||
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_create(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let note = self.to_apub(context.pool()).await?;
|
let note = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let recipient_id = self.recipient_id;
|
let recipient_id = self.recipient_id;
|
||||||
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
let recipient =
|
||||||
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
||||||
|
|
||||||
let mut create = Create::new(
|
let mut create = Create::new(
|
||||||
creator.actor_id.to_owned().into_inner(),
|
creator.actor_id.to_owned().into_inner(),
|
||||||
|
@ -46,11 +47,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Send out information about an edited private message, to the followers of the community.
|
/// Send out information about an edited private message, to the followers of the community.
|
||||||
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_update(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let note = self.to_apub(context.pool()).await?;
|
let note = self.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
let recipient_id = self.recipient_id;
|
let recipient_id = self.recipient_id;
|
||||||
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
let recipient =
|
||||||
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
||||||
|
|
||||||
let mut update = Update::new(
|
let mut update = Update::new(
|
||||||
creator.actor_id.to_owned().into_inner(),
|
creator.actor_id.to_owned().into_inner(),
|
||||||
|
@ -65,9 +67,10 @@ impl ApubObjectType for PrivateMessage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_delete(&self, creator: &Person, context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
let recipient_id = self.recipient_id;
|
let recipient_id = self.recipient_id;
|
||||||
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
let recipient =
|
||||||
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
||||||
|
|
||||||
let mut delete = Delete::new(
|
let mut delete = Delete::new(
|
||||||
creator.actor_id.to_owned().into_inner(),
|
creator.actor_id.to_owned().into_inner(),
|
||||||
|
@ -84,11 +87,12 @@ impl ApubObjectType for PrivateMessage {
|
||||||
|
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let recipient_id = self.recipient_id;
|
let recipient_id = self.recipient_id;
|
||||||
let recipient = blocking(context.pool(), move |conn| User_::read(conn, recipient_id)).await??;
|
let recipient =
|
||||||
|
blocking(context.pool(), move |conn| Person::read(conn, recipient_id)).await??;
|
||||||
|
|
||||||
let mut delete = Delete::new(
|
let mut delete = Delete::new(
|
||||||
creator.actor_id.to_owned().into_inner(),
|
creator.actor_id.to_owned().into_inner(),
|
||||||
|
@ -113,13 +117,13 @@ impl ApubObjectType for PrivateMessage {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_remove(&self, _mod_: &User_, _context: &LemmyContext) -> Result<(), LemmyError> {
|
async fn send_remove(&self, _mod_: &Person, _context: &LemmyContext) -> Result<(), LemmyError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn send_undo_remove(
|
async fn send_undo_remove(
|
||||||
&self,
|
&self,
|
||||||
_mod_: &User_,
|
_mod_: &Person,
|
||||||
_context: &LemmyContext,
|
_context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
unimplemented!()
|
unimplemented!()
|
||||||
|
|
|
@ -21,7 +21,7 @@ use background_jobs::{
|
||||||
};
|
};
|
||||||
use itertools::Itertools;
|
use itertools::Itertools;
|
||||||
use lemmy_db_queries::DbPool;
|
use lemmy_db_queries::DbPool;
|
||||||
use lemmy_db_schema::source::{community::Community, user::User_};
|
use lemmy_db_schema::source::{community::Community, person::Person};
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::{debug, warn};
|
use log::{debug, warn};
|
||||||
|
@ -112,7 +112,7 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends an activity from a local user to a remote community.
|
/// Sends an activity from a local person to a remote community.
|
||||||
///
|
///
|
||||||
/// * `activity` the activity to send
|
/// * `activity` the activity to send
|
||||||
/// * `creator` the creator of the activity
|
/// * `creator` the creator of the activity
|
||||||
|
@ -120,7 +120,7 @@ where
|
||||||
///
|
///
|
||||||
pub(crate) async fn send_to_community<T, Kind>(
|
pub(crate) async fn send_to_community<T, Kind>(
|
||||||
activity: T,
|
activity: T,
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>
|
) -> Result<(), LemmyError>
|
||||||
|
@ -157,13 +157,13 @@ where
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends notification to any users mentioned in a comment
|
/// Sends notification to any persons mentioned in a comment
|
||||||
///
|
///
|
||||||
/// * `creator` user who created the comment
|
/// * `creator` person who created the comment
|
||||||
/// * `mentions` list of inboxes of users which are mentioned in the comment
|
/// * `mentions` list of inboxes of persons which are mentioned in the comment
|
||||||
/// * `activity` either a `Create/Note` or `Update/Note`
|
/// * `activity` either a `Create/Note` or `Update/Note`
|
||||||
pub(crate) async fn send_comment_mentions<T, Kind>(
|
pub(crate) async fn send_comment_mentions<T, Kind>(
|
||||||
creator: &User_,
|
creator: &Person,
|
||||||
mentions: Vec<Url>,
|
mentions: Vec<Url>,
|
||||||
activity: T,
|
activity: T,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
|
@ -223,7 +223,7 @@ where
|
||||||
let hostname = Settings::get().get_hostname_without_port()?;
|
let hostname = Settings::get().get_hostname_without_port()?;
|
||||||
let inboxes: Vec<&Url> = inboxes
|
let inboxes: Vec<&Url> = inboxes
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|i| i.domain().unwrap() != hostname)
|
.filter(|i| i.domain().expect("valid inbox url") != hostname)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
let activity = activity.into_any_base()?;
|
let activity = activity.into_any_base()?;
|
||||||
|
|
|
@ -6,12 +6,11 @@ pub(crate) fn lemmy_context() -> Result<Vec<AnyBase>, LemmyError> {
|
||||||
let context_ext = AnyBase::from_arbitrary_json(json!(
|
let context_ext = AnyBase::from_arbitrary_json(json!(
|
||||||
{
|
{
|
||||||
"sc": "http://schema.org#",
|
"sc": "http://schema.org#",
|
||||||
"category": "sc:category",
|
|
||||||
"sensitive": "as:sensitive",
|
"sensitive": "as:sensitive",
|
||||||
"stickied": "as:stickied",
|
"stickied": "as:stickied",
|
||||||
"comments_enabled": {
|
"comments_enabled": {
|
||||||
"kind": "sc:Boolean",
|
"kind": "sc:Boolean",
|
||||||
"id": "pt:commentsEnabled"
|
"id": "pt:commentsEnabled"
|
||||||
}
|
}
|
||||||
}))?;
|
}))?;
|
||||||
Ok(vec![AnyBase::from(context()), context_ext])
|
Ok(vec![AnyBase::from(context()), context_ext])
|
||||||
|
|
|
@ -95,7 +95,7 @@ pub(crate) fn verify_signature(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extension for actor public key, which is needed on user and community for HTTP signatures.
|
/// Extension for actor public key, which is needed on person and community for HTTP signatures.
|
||||||
///
|
///
|
||||||
/// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
|
/// Taken from: https://docs.rs/activitystreams/0.5.0-alpha.17/activitystreams/ext/index.html
|
||||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
fetcher::{
|
fetcher::{
|
||||||
fetch::fetch_remote_object,
|
fetch::fetch_remote_object,
|
||||||
get_or_fetch_and_upsert_user,
|
get_or_fetch_and_upsert_person,
|
||||||
is_deleted,
|
is_deleted,
|
||||||
should_refetch_actor,
|
should_refetch_actor,
|
||||||
},
|
},
|
||||||
inbox::user_inbox::receive_announce,
|
inbox::person_inbox::receive_announce,
|
||||||
objects::FromApub,
|
objects::FromApub,
|
||||||
GroupExt,
|
GroupExt,
|
||||||
};
|
};
|
||||||
|
@ -92,7 +92,7 @@ async fn fetch_remote_community(
|
||||||
let mut creator_and_moderators = Vec::new();
|
let mut creator_and_moderators = Vec::new();
|
||||||
|
|
||||||
for uri in creator_and_moderator_uris {
|
for uri in creator_and_moderator_uris {
|
||||||
let c_or_m = get_or_fetch_and_upsert_user(uri, context, recursion_counter).await?;
|
let c_or_m = get_or_fetch_and_upsert_person(uri, context, recursion_counter).await?;
|
||||||
|
|
||||||
creator_and_moderators.push(c_or_m);
|
creator_and_moderators.push(c_or_m);
|
||||||
}
|
}
|
||||||
|
@ -104,7 +104,7 @@ async fn fetch_remote_community(
|
||||||
for mod_ in creator_and_moderators {
|
for mod_ in creator_and_moderators {
|
||||||
let community_moderator_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id,
|
community_id,
|
||||||
user_id: mod_.id,
|
person_id: mod_.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
CommunityModerator::join(conn, &community_moderator_form)?;
|
CommunityModerator::join(conn, &community_moderator_form)?;
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
pub(crate) mod community;
|
pub(crate) mod community;
|
||||||
mod fetch;
|
mod fetch;
|
||||||
pub(crate) mod objects;
|
pub(crate) mod objects;
|
||||||
|
pub(crate) mod person;
|
||||||
pub mod search;
|
pub mod search;
|
||||||
pub(crate) mod user;
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
fetcher::{
|
fetcher::{
|
||||||
community::get_or_fetch_and_upsert_community,
|
community::get_or_fetch_and_upsert_community,
|
||||||
fetch::FetchError,
|
fetch::FetchError,
|
||||||
user::get_or_fetch_and_upsert_user,
|
person::get_or_fetch_and_upsert_person,
|
||||||
},
|
},
|
||||||
ActorType,
|
ActorType,
|
||||||
};
|
};
|
||||||
|
@ -37,8 +37,8 @@ where
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get a remote actor from its apub ID (either a user or a community). Thin wrapper around
|
/// Get a remote actor from its apub ID (either a person or a community). Thin wrapper around
|
||||||
/// `get_or_fetch_and_upsert_user()` and `get_or_fetch_and_upsert_community()`.
|
/// `get_or_fetch_and_upsert_person()` and `get_or_fetch_and_upsert_community()`.
|
||||||
///
|
///
|
||||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||||
|
@ -50,7 +50,7 @@ pub(crate) async fn get_or_fetch_and_upsert_actor(
|
||||||
let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
|
let community = get_or_fetch_and_upsert_community(apub_id, context, recursion_counter).await;
|
||||||
let actor: Box<dyn ActorType> = match community {
|
let actor: Box<dyn ActorType> = match community {
|
||||||
Ok(c) => Box::new(c),
|
Ok(c) => Box::new(c),
|
||||||
Err(_) => Box::new(get_or_fetch_and_upsert_user(apub_id, context, recursion_counter).await?),
|
Err(_) => Box::new(get_or_fetch_and_upsert_person(apub_id, context, recursion_counter).await?),
|
||||||
};
|
};
|
||||||
Ok(actor)
|
Ok(actor)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,65 +6,67 @@ use crate::{
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{source::user::User, ApubObject};
|
use lemmy_db_queries::{source::person::Person_, ApubObject};
|
||||||
use lemmy_db_schema::source::user::User_;
|
use lemmy_db_schema::source::person::Person;
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Get a user from its apub ID.
|
/// Get a person from its apub ID.
|
||||||
///
|
///
|
||||||
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
/// If it exists locally and `!should_refetch_actor()`, it is returned directly from the database.
|
||||||
/// Otherwise it is fetched from the remote instance, stored and returned.
|
/// Otherwise it is fetched from the remote instance, stored and returned.
|
||||||
pub(crate) async fn get_or_fetch_and_upsert_user(
|
pub(crate) async fn get_or_fetch_and_upsert_person(
|
||||||
apub_id: &Url,
|
apub_id: &Url,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
recursion_counter: &mut i32,
|
recursion_counter: &mut i32,
|
||||||
) -> Result<User_, LemmyError> {
|
) -> Result<Person, LemmyError> {
|
||||||
let apub_id_owned = apub_id.to_owned();
|
let apub_id_owned = apub_id.to_owned();
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::read_from_apub_id(conn, &apub_id_owned.into())
|
Person::read_from_apub_id(conn, &apub_id_owned.into())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
match user {
|
match person {
|
||||||
// If its older than a day, re-fetch it
|
// If its older than a day, re-fetch it
|
||||||
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
|
Ok(u) if !u.local && should_refetch_actor(u.last_refreshed_at) => {
|
||||||
debug!("Fetching and updating from remote user: {}", apub_id);
|
debug!("Fetching and updating from remote person: {}", apub_id);
|
||||||
let person =
|
let person =
|
||||||
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await;
|
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await;
|
||||||
|
|
||||||
if is_deleted(&person) {
|
if is_deleted(&person) {
|
||||||
// TODO: use User_::update_deleted() once implemented
|
// TODO: use Person::update_deleted() once implemented
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
User_::delete_account(conn, u.id)
|
Person::delete_account(conn, u.id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
return Err(anyhow!("User was deleted by remote instance").into());
|
return Err(anyhow!("Person was deleted by remote instance").into());
|
||||||
} else if person.is_err() {
|
} else if person.is_err() {
|
||||||
return Ok(u);
|
return Ok(u);
|
||||||
}
|
}
|
||||||
|
|
||||||
let user = User_::from_apub(&person?, context, apub_id.to_owned(), recursion_counter).await?;
|
let person =
|
||||||
|
Person::from_apub(&person?, context, apub_id.to_owned(), recursion_counter).await?;
|
||||||
|
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
User_::mark_as_updated(conn, user_id)
|
Person::mark_as_updated(conn, person_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
Ok(user)
|
Ok(person)
|
||||||
}
|
}
|
||||||
Ok(u) => Ok(u),
|
Ok(u) => Ok(u),
|
||||||
Err(NotFound {}) => {
|
Err(NotFound {}) => {
|
||||||
debug!("Fetching and creating remote user: {}", apub_id);
|
debug!("Fetching and creating remote person: {}", apub_id);
|
||||||
let person =
|
let person =
|
||||||
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?;
|
fetch_remote_object::<PersonExt>(context.client(), apub_id, recursion_counter).await?;
|
||||||
|
|
||||||
let user = User_::from_apub(&person, context, apub_id.to_owned(), recursion_counter).await?;
|
let person =
|
||||||
|
Person::from_apub(&person, context, apub_id.to_owned(), recursion_counter).await?;
|
||||||
|
|
||||||
Ok(user)
|
Ok(person)
|
||||||
}
|
}
|
||||||
Err(e) => Err(e.into()),
|
Err(e) => Err(e.into()),
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ use crate::{
|
||||||
fetcher::{
|
fetcher::{
|
||||||
fetch::fetch_remote_object,
|
fetch::fetch_remote_object,
|
||||||
get_or_fetch_and_upsert_community,
|
get_or_fetch_and_upsert_community,
|
||||||
get_or_fetch_and_upsert_user,
|
get_or_fetch_and_upsert_person,
|
||||||
is_deleted,
|
is_deleted,
|
||||||
},
|
},
|
||||||
find_object_by_id,
|
find_object_by_id,
|
||||||
|
@ -20,21 +20,21 @@ use lemmy_db_queries::{
|
||||||
source::{
|
source::{
|
||||||
comment::Comment_,
|
comment::Comment_,
|
||||||
community::Community_,
|
community::Community_,
|
||||||
|
person::Person_,
|
||||||
post::Post_,
|
post::Post_,
|
||||||
private_message::PrivateMessage_,
|
private_message::PrivateMessage_,
|
||||||
user::User,
|
|
||||||
},
|
},
|
||||||
SearchType,
|
SearchType,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::Comment,
|
comment::Comment,
|
||||||
community::Community,
|
community::Community,
|
||||||
|
person::Person,
|
||||||
post::Post,
|
post::Post,
|
||||||
private_message::PrivateMessage,
|
private_message::PrivateMessage,
|
||||||
user::User_,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_views::{comment_view::CommentView, post_view::PostView};
|
use lemmy_db_views::{comment_view::CommentView, post_view::PostView};
|
||||||
use lemmy_db_views_actor::{community_view::CommunityView, user_view::UserViewSafe};
|
use lemmy_db_views_actor::{community_view::CommunityView, person_view::PersonViewSafe};
|
||||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::debug;
|
use log::debug;
|
||||||
|
@ -66,7 +66,7 @@ pub async fn search_by_apub_id(
|
||||||
debug!("Search for {}", query);
|
debug!("Search for {}", query);
|
||||||
let split = query.split('@').collect::<Vec<&str>>();
|
let split = query.split('@').collect::<Vec<&str>>();
|
||||||
|
|
||||||
// User type will look like ['', username, instance]
|
// Person type will look like ['', username, instance]
|
||||||
// Community will look like [!community, instance]
|
// Community will look like [!community, instance]
|
||||||
let (name, instance) = if split.len() == 3 {
|
let (name, instance) = if split.len() == 3 {
|
||||||
(format!("/u/{}", split[1]), split[2])
|
(format!("/u/{}", split[1]), split[2])
|
||||||
|
@ -122,13 +122,13 @@ async fn build_response(
|
||||||
|
|
||||||
match fetch_response {
|
match fetch_response {
|
||||||
SearchAcceptedObjects::Person(p) => {
|
SearchAcceptedObjects::Person(p) => {
|
||||||
let user_uri = p.inner.id(domain)?.context("person has no id")?;
|
let person_uri = p.inner.id(domain)?.context("person has no id")?;
|
||||||
|
|
||||||
let user = get_or_fetch_and_upsert_user(&user_uri, context, recursion_counter).await?;
|
let person = get_or_fetch_and_upsert_person(&person_uri, context, recursion_counter).await?;
|
||||||
|
|
||||||
response.users = vec![
|
response.users = vec![
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
UserViewSafe::read(conn, user.id)
|
PersonViewSafe::read(conn, person.id)
|
||||||
})
|
})
|
||||||
.await??,
|
.await??,
|
||||||
];
|
];
|
||||||
|
@ -182,10 +182,10 @@ async fn delete_object_locally(query_url: &Url, context: &LemmyContext) -> Resul
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
Object::User(u) => {
|
Object::Person(u) => {
|
||||||
// TODO: implement update_deleted() for user, move it to ApubObject trait
|
// TODO: implement update_deleted() for user, move it to ApubObject trait
|
||||||
blocking(context.pool(), move |conn| {
|
blocking(context.pool(), move |conn| {
|
||||||
User_::delete_account(conn, u.id)
|
Person::delete_account(conn, u.id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ use actix_web::{body::Body, web, web::Path, HttpResponse};
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::comment::Comment;
|
use lemmy_db_schema::{source::comment::Comment, CommentId};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -21,7 +21,7 @@ pub async fn get_apub_comment(
|
||||||
info: Path<CommentQuery>,
|
info: Path<CommentQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let id = info.comment_id.parse::<i32>()?;
|
let id = CommentId(info.comment_id.parse::<i32>()?);
|
||||||
let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??;
|
let comment = blocking(context.pool(), move |conn| Comment::read(conn, id)).await??;
|
||||||
if !comment.local {
|
if !comment.local {
|
||||||
return Err(NotFound.into());
|
return Err(NotFound.into());
|
||||||
|
|
|
@ -7,11 +7,12 @@ use lemmy_db_schema::source::activity::Activity;
|
||||||
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
use lemmy_utils::{settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod person;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod user;
|
|
||||||
|
|
||||||
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
|
/// Convert the data to json and turn it into an HTTP Response with the correct ActivityPub
|
||||||
/// headers.
|
/// headers.
|
||||||
|
@ -46,12 +47,13 @@ pub async fn get_activity(
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let settings = Settings::get();
|
let settings = Settings::get();
|
||||||
let activity_id = format!(
|
let activity_id = Url::parse(&format!(
|
||||||
"{}/activities/{}/{}",
|
"{}/activities/{}/{}",
|
||||||
settings.get_protocol_and_hostname(),
|
settings.get_protocol_and_hostname(),
|
||||||
info.type_,
|
info.type_,
|
||||||
info.id
|
info.id
|
||||||
);
|
))?
|
||||||
|
.into();
|
||||||
let activity = blocking(context.pool(), move |conn| {
|
let activity = blocking(context.pool(), move |conn| {
|
||||||
Activity::read_from_apub_id(&conn, &activity_id)
|
Activity::read_from_apub_id(&conn, &activity_id)
|
||||||
})
|
})
|
||||||
|
|
|
@ -10,69 +10,69 @@ use activitystreams::{
|
||||||
};
|
};
|
||||||
use actix_web::{body::Body, web, HttpResponse};
|
use actix_web::{body::Body, web, HttpResponse};
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::source::user::User;
|
use lemmy_db_queries::source::person::Person_;
|
||||||
use lemmy_db_schema::source::user::User_;
|
use lemmy_db_schema::source::person::Person;
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[derive(Deserialize)]
|
#[derive(Deserialize)]
|
||||||
pub struct UserQuery {
|
pub struct PersonQuery {
|
||||||
user_name: String,
|
user_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the ActivityPub json representation of a local user over HTTP.
|
/// Return the ActivityPub json representation of a local person over HTTP.
|
||||||
pub async fn get_apub_user_http(
|
pub async fn get_apub_person_http(
|
||||||
info: web::Path<UserQuery>,
|
info: web::Path<PersonQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let user_name = info.into_inner().user_name;
|
let user_name = info.into_inner().user_name;
|
||||||
// TODO: this needs to be able to read deleted users, so that it can send tombstones
|
// TODO: this needs to be able to read deleted persons, so that it can send tombstones
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::find_by_email_or_username(conn, &user_name)
|
Person::find_by_name(conn, &user_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
if !user.deleted {
|
if !person.deleted {
|
||||||
let apub = user.to_apub(context.pool()).await?;
|
let apub = person.to_apub(context.pool()).await?;
|
||||||
|
|
||||||
Ok(create_apub_response(&apub))
|
Ok(create_apub_response(&apub))
|
||||||
} else {
|
} else {
|
||||||
Ok(create_apub_tombstone_response(&user.to_tombstone()?))
|
Ok(create_apub_tombstone_response(&person.to_tombstone()?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_apub_user_outbox(
|
pub async fn get_apub_person_outbox(
|
||||||
info: web::Path<UserQuery>,
|
info: web::Path<PersonQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::read_from_name(&conn, &info.user_name)
|
Person::find_by_name(&conn, &info.user_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
// TODO: populate the user outbox
|
// TODO: populate the person outbox
|
||||||
let mut collection = OrderedCollection::new();
|
let mut collection = OrderedCollection::new();
|
||||||
collection
|
collection
|
||||||
.set_many_items(Vec::<Url>::new())
|
.set_many_items(Vec::<Url>::new())
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
.set_id(user.get_outbox_url()?)
|
.set_id(person.get_outbox_url()?)
|
||||||
.set_total_items(0_u64);
|
.set_total_items(0_u64);
|
||||||
Ok(create_apub_response(&collection))
|
Ok(create_apub_response(&collection))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_apub_user_inbox(
|
pub async fn get_apub_person_inbox(
|
||||||
info: web::Path<UserQuery>,
|
info: web::Path<PersonQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::read_from_name(&conn, &info.user_name)
|
Person::find_by_name(&conn, &info.user_name)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
||||||
let mut collection = OrderedCollection::new();
|
let mut collection = OrderedCollection::new();
|
||||||
collection
|
collection
|
||||||
.set_id(format!("{}/inbox", user.actor_id.into_inner()).parse()?)
|
.set_id(format!("{}/inbox", person.actor_id.into_inner()).parse()?)
|
||||||
.set_many_contexts(lemmy_context()?);
|
.set_many_contexts(lemmy_context()?);
|
||||||
Ok(create_apub_response(&collection))
|
Ok(create_apub_response(&collection))
|
||||||
}
|
}
|
|
@ -6,7 +6,7 @@ use actix_web::{body::Body, web, HttpResponse};
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::Crud;
|
use lemmy_db_queries::Crud;
|
||||||
use lemmy_db_schema::source::post::Post;
|
use lemmy_db_schema::{source::post::Post, PostId};
|
||||||
use lemmy_utils::LemmyError;
|
use lemmy_utils::LemmyError;
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
@ -21,7 +21,7 @@ pub async fn get_apub_post(
|
||||||
info: web::Path<PostQuery>,
|
info: web::Path<PostQuery>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse<Body>, LemmyError> {
|
) -> Result<HttpResponse<Body>, LemmyError> {
|
||||||
let id = info.post_id.parse::<i32>()?;
|
let id = PostId(info.post_id.parse::<i32>()?);
|
||||||
let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??;
|
let post = blocking(context.pool(), move |conn| Post::read(conn, id)).await??;
|
||||||
if !post.local {
|
if !post.local {
|
||||||
return Err(NotFound.into());
|
return Err(NotFound.into());
|
||||||
|
|
|
@ -28,11 +28,14 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable};
|
use lemmy_db_queries::{source::community::Community_, ApubObject, DbPool, Followable};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm},
|
source::{
|
||||||
user::User_,
|
community::{Community, CommunityFollower, CommunityFollowerForm},
|
||||||
|
person::Person,
|
||||||
|
},
|
||||||
|
CommunityId,
|
||||||
};
|
};
|
||||||
use lemmy_db_views_actor::community_user_ban_view::CommunityUserBanView;
|
use lemmy_db_views_actor::community_person_ban_view::CommunityPersonBanView;
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
@ -44,8 +47,8 @@ use url::Url;
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
pub enum CommunityValidTypes {
|
pub enum CommunityValidTypes {
|
||||||
Follow, // follow request from a user
|
Follow, // follow request from a person
|
||||||
Undo, // unfollow from a user
|
Undo, // unfollow from a person
|
||||||
Create, // create post or comment
|
Create, // create post or comment
|
||||||
Update, // update post or comment
|
Update, // update post or comment
|
||||||
Like, // upvote post or comment
|
Like, // upvote post or comment
|
||||||
|
@ -113,21 +116,21 @@ pub(crate) async fn community_receive_message(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
// Only users can send activities to the community, so we can get the actor as user
|
// Only persons can send activities to the community, so we can get the actor as person
|
||||||
// unconditionally.
|
// unconditionally.
|
||||||
let actor_id = actor.actor_id();
|
let actor_id = actor.actor_id();
|
||||||
let user = blocking(&context.pool(), move |conn| {
|
let person = blocking(&context.pool(), move |conn| {
|
||||||
User_::read_from_apub_id(&conn, &actor_id.into())
|
Person::read_from_apub_id(&conn, &actor_id.into())
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
check_community_or_site_ban(&user, to_community.id, context.pool()).await?;
|
check_community_or_site_ban(&person, to_community.id, context.pool()).await?;
|
||||||
|
|
||||||
let any_base = activity.clone().into_any_base()?;
|
let any_base = activity.clone().into_any_base()?;
|
||||||
let actor_url = actor.actor_id();
|
let actor_url = actor.actor_id();
|
||||||
let activity_kind = activity.kind().context(location_info!())?;
|
let activity_kind = activity.kind().context(location_info!())?;
|
||||||
let do_announce = match activity_kind {
|
let do_announce = match activity_kind {
|
||||||
CommunityValidTypes::Follow => {
|
CommunityValidTypes::Follow => {
|
||||||
handle_follow(any_base.clone(), user, &to_community, &context).await?;
|
handle_follow(any_base.clone(), person, &to_community, &context).await?;
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
CommunityValidTypes::Undo => {
|
CommunityValidTypes::Undo => {
|
||||||
|
@ -162,7 +165,7 @@ pub(crate) async fn community_receive_message(
|
||||||
}
|
}
|
||||||
CommunityValidTypes::Remove => {
|
CommunityValidTypes::Remove => {
|
||||||
// TODO: we dont support remote mods, so this is ignored for now
|
// TODO: we dont support remote mods, so this is ignored for now
|
||||||
//receive_remove_for_community(context, any_base.clone(), &user_url).await?
|
//receive_remove_for_community(context, any_base.clone(), &person_url).await?
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -178,20 +181,20 @@ pub(crate) async fn community_receive_message(
|
||||||
Ok(HttpResponse::Ok().finish())
|
Ok(HttpResponse::Ok().finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle a follow request from a remote user, adding the user as follower and returning an
|
/// Handle a follow request from a remote person, adding the person as follower and returning an
|
||||||
/// Accept activity.
|
/// Accept activity.
|
||||||
async fn handle_follow(
|
async fn handle_follow(
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
user: User_,
|
person: Person,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
let follow = Follow::from_any_base(activity)?.context(location_info!())?;
|
let follow = Follow::from_any_base(activity)?.context(location_info!())?;
|
||||||
verify_activity_domains_valid(&follow, &user.actor_id(), false)?;
|
verify_activity_domains_valid(&follow, &person.actor_id(), false)?;
|
||||||
|
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -226,27 +229,27 @@ async fn handle_undo(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle `Undo/Follow` from a user, removing the user from followers list.
|
/// Handle `Undo/Follow` from a person, removing the person from followers list.
|
||||||
async fn handle_undo_follow(
|
async fn handle_undo_follow(
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
user_url: Url,
|
person_url: Url,
|
||||||
community: &Community,
|
community: &Community,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let undo = Undo::from_any_base(activity)?.context(location_info!())?;
|
let undo = Undo::from_any_base(activity)?.context(location_info!())?;
|
||||||
verify_activity_domains_valid(&undo, &user_url, true)?;
|
verify_activity_domains_valid(&undo, &person_url, true)?;
|
||||||
|
|
||||||
let object = undo.object().to_owned().one().context(location_info!())?;
|
let object = undo.object().to_owned().one().context(location_info!())?;
|
||||||
let follow = Follow::from_any_base(object)?.context(location_info!())?;
|
let follow = Follow::from_any_base(object)?.context(location_info!())?;
|
||||||
verify_activity_domains_valid(&follow, &user_url, false)?;
|
verify_activity_domains_valid(&follow, &person_url, false)?;
|
||||||
|
|
||||||
let user = blocking(&context.pool(), move |conn| {
|
let person = blocking(&context.pool(), move |conn| {
|
||||||
User_::read_from_apub_id(&conn, &user_url.into())
|
Person::read_from_apub_id(&conn, &person_url.into())
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
user_id: user.id,
|
person_id: person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -260,17 +263,18 @@ async fn handle_undo_follow(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn check_community_or_site_ban(
|
pub(crate) async fn check_community_or_site_ban(
|
||||||
user: &User_,
|
person: &Person,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
if user.banned {
|
if person.banned {
|
||||||
return Err(anyhow!("User is banned from site").into());
|
return Err(anyhow!("Person is banned from site").into());
|
||||||
}
|
}
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
let is_banned = move |conn: &'_ _| CommunityUserBanView::get(conn, user_id, community_id).is_ok();
|
let is_banned =
|
||||||
|
move |conn: &'_ _| CommunityPersonBanView::get(conn, person_id, community_id).is_ok();
|
||||||
if blocking(pool, is_banned).await? {
|
if blocking(pool, is_banned).await? {
|
||||||
return Err(anyhow!("User is banned from community").into());
|
return Err(anyhow!("Person is banned from community").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -18,7 +18,7 @@ use lemmy_db_queries::{
|
||||||
ApubObject,
|
ApubObject,
|
||||||
DbPool,
|
DbPool,
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{activity::Activity, community::Community, user::User_};
|
use lemmy_db_schema::source::{activity::Activity, community::Community, person::Person};
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
@ -26,9 +26,9 @@ use std::fmt::Debug;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
pub mod community_inbox;
|
pub mod community_inbox;
|
||||||
|
pub mod person_inbox;
|
||||||
mod receive_for_community;
|
mod receive_for_community;
|
||||||
pub mod shared_inbox;
|
pub mod shared_inbox;
|
||||||
pub mod user_inbox;
|
|
||||||
|
|
||||||
pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError>
|
pub(crate) fn get_activity_id<T, Kind>(activity: &T, creator_uri: &Url) -> Result<Url, LemmyError>
|
||||||
where
|
where
|
||||||
|
@ -45,7 +45,7 @@ pub(crate) async fn is_activity_already_known(
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
activity_id: &Url,
|
activity_id: &Url,
|
||||||
) -> Result<bool, LemmyError> {
|
) -> Result<bool, LemmyError> {
|
||||||
let activity_id = activity_id.to_string();
|
let activity_id = activity_id.to_owned().into();
|
||||||
let existing = blocking(pool, move |conn| {
|
let existing = blocking(pool, move |conn| {
|
||||||
Activity::read_from_apub_id(&conn, &activity_id)
|
Activity::read_from_apub_id(&conn, &activity_id)
|
||||||
})
|
})
|
||||||
|
@ -119,17 +119,17 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if `to_and_cc` contains at least one local user.
|
/// Returns true if `to_and_cc` contains at least one local user.
|
||||||
pub(crate) async fn is_addressed_to_local_user(
|
pub(crate) async fn is_addressed_to_local_person(
|
||||||
to_and_cc: &[Url],
|
to_and_cc: &[Url],
|
||||||
pool: &DbPool,
|
pool: &DbPool,
|
||||||
) -> Result<bool, LemmyError> {
|
) -> Result<bool, LemmyError> {
|
||||||
for url in to_and_cc {
|
for url in to_and_cc {
|
||||||
let url = url.to_owned();
|
let url = url.to_owned();
|
||||||
let user = blocking(&pool, move |conn| {
|
let person = blocking(&pool, move |conn| {
|
||||||
User_::read_from_apub_id(&conn, &url.into())
|
Person::read_from_apub_id(&conn, &url.into())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(u) = user {
|
if let Ok(u) = person {
|
||||||
if u.local {
|
if u.local {
|
||||||
return Ok(true);
|
return Ok(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,7 @@ use crate::{
|
||||||
inbox_verify_http_signature,
|
inbox_verify_http_signature,
|
||||||
is_activity_already_known,
|
is_activity_already_known,
|
||||||
is_addressed_to_community_followers,
|
is_addressed_to_community_followers,
|
||||||
is_addressed_to_local_user,
|
is_addressed_to_local_person,
|
||||||
is_addressed_to_public,
|
is_addressed_to_public,
|
||||||
receive_for_community::{
|
receive_for_community::{
|
||||||
receive_create_for_community,
|
receive_create_for_community,
|
||||||
|
@ -49,11 +49,11 @@ use actix_web::{web, HttpRequest, HttpResponse};
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use diesel::NotFound;
|
use diesel::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{source::user::User, ApubObject, Followable};
|
use lemmy_db_queries::{source::person::Person_, ApubObject, Followable};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
community::{Community, CommunityFollower},
|
community::{Community, CommunityFollower},
|
||||||
|
person::Person,
|
||||||
private_message::PrivateMessage,
|
private_message::PrivateMessage,
|
||||||
user::User_,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::{location_info, LemmyError};
|
use lemmy_utils::{location_info, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -63,10 +63,10 @@ use std::fmt::Debug;
|
||||||
use strum_macros::EnumString;
|
use strum_macros::EnumString;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Allowed activities for user inbox.
|
/// Allowed activities for person inbox.
|
||||||
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
|
#[derive(Clone, Debug, Eq, Ord, PartialEq, PartialOrd, Deserialize, Serialize)]
|
||||||
#[serde(rename_all = "PascalCase")]
|
#[serde(rename_all = "PascalCase")]
|
||||||
pub enum UserValidTypes {
|
pub enum PersonValidTypes {
|
||||||
Accept, // community accepted our follow request
|
Accept, // community accepted our follow request
|
||||||
Create, // create private message
|
Create, // create private message
|
||||||
Update, // edit private message
|
Update, // edit private message
|
||||||
|
@ -76,12 +76,12 @@ pub enum UserValidTypes {
|
||||||
Announce, // post, comment or vote in community
|
Announce, // post, comment or vote in community
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UserAcceptedActivities = ActorAndObject<UserValidTypes>;
|
pub type PersonAcceptedActivities = ActorAndObject<PersonValidTypes>;
|
||||||
|
|
||||||
/// Handler for all incoming activities to user inboxes.
|
/// Handler for all incoming activities to person inboxes.
|
||||||
pub async fn user_inbox(
|
pub async fn person_inbox(
|
||||||
request: HttpRequest,
|
request: HttpRequest,
|
||||||
input: web::Json<UserAcceptedActivities>,
|
input: web::Json<PersonAcceptedActivities>,
|
||||||
path: web::Path<String>,
|
path: web::Path<String>,
|
||||||
context: web::Data<LemmyContext>,
|
context: web::Data<LemmyContext>,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
|
@ -98,29 +98,29 @@ pub async fn user_inbox(
|
||||||
|
|
||||||
// Check if the activity is actually meant for us
|
// Check if the activity is actually meant for us
|
||||||
let username = path.into_inner();
|
let username = path.into_inner();
|
||||||
let user = blocking(&context.pool(), move |conn| {
|
let person = blocking(&context.pool(), move |conn| {
|
||||||
User_::read_from_name(&conn, &username)
|
Person::find_by_name(&conn, &username)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
let to_and_cc = get_activity_to_and_cc(&activity);
|
let to_and_cc = get_activity_to_and_cc(&activity);
|
||||||
// TODO: we should also accept activities that are sent to community followers
|
// TODO: we should also accept activities that are sent to community followers
|
||||||
if !to_and_cc.contains(&&user.actor_id()) {
|
if !to_and_cc.contains(&&person.actor_id()) {
|
||||||
return Err(anyhow!("Activity delivered to wrong user").into());
|
return Err(anyhow!("Activity delivered to wrong person").into());
|
||||||
}
|
}
|
||||||
|
|
||||||
assert_activity_not_local(&activity)?;
|
assert_activity_not_local(&activity)?;
|
||||||
insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?;
|
insert_activity(&activity_id, activity.clone(), false, true, context.pool()).await?;
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"User {} received activity {:?} from {}",
|
"Person {} received activity {:?} from {}",
|
||||||
user.name,
|
person.name,
|
||||||
&activity.id_unchecked(),
|
&activity.id_unchecked(),
|
||||||
&actor.actor_id()
|
&actor.actor_id()
|
||||||
);
|
);
|
||||||
|
|
||||||
user_receive_message(
|
person_receive_message(
|
||||||
activity.clone(),
|
activity.clone(),
|
||||||
Some(user.clone()),
|
Some(person.clone()),
|
||||||
actor.as_ref(),
|
actor.as_ref(),
|
||||||
&context,
|
&context,
|
||||||
request_counter,
|
request_counter,
|
||||||
|
@ -129,36 +129,43 @@ pub async fn user_inbox(
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete
|
/// Receives Accept/Follow, Announce, private messages and community (undo) remove, (undo) delete
|
||||||
pub(crate) async fn user_receive_message(
|
pub(crate) async fn person_receive_message(
|
||||||
activity: UserAcceptedActivities,
|
activity: PersonAcceptedActivities,
|
||||||
to_user: Option<User_>,
|
to_person: Option<Person>,
|
||||||
actor: &dyn ActorType,
|
actor: &dyn ActorType,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<HttpResponse, LemmyError> {
|
) -> Result<HttpResponse, LemmyError> {
|
||||||
is_for_user_inbox(context, &activity).await?;
|
is_for_person_inbox(context, &activity).await?;
|
||||||
|
|
||||||
let any_base = activity.clone().into_any_base()?;
|
let any_base = activity.clone().into_any_base()?;
|
||||||
let kind = activity.kind().context(location_info!())?;
|
let kind = activity.kind().context(location_info!())?;
|
||||||
let actor_url = actor.actor_id();
|
let actor_url = actor.actor_id();
|
||||||
match kind {
|
match kind {
|
||||||
UserValidTypes::Accept => {
|
PersonValidTypes::Accept => {
|
||||||
receive_accept(&context, any_base, actor, to_user.unwrap(), request_counter).await?;
|
receive_accept(
|
||||||
|
&context,
|
||||||
|
any_base,
|
||||||
|
actor,
|
||||||
|
to_person.expect("person provided"),
|
||||||
|
request_counter,
|
||||||
|
)
|
||||||
|
.await?;
|
||||||
}
|
}
|
||||||
UserValidTypes::Announce => {
|
PersonValidTypes::Announce => {
|
||||||
receive_announce(&context, any_base, actor, request_counter).await?
|
receive_announce(&context, any_base, actor, request_counter).await?
|
||||||
}
|
}
|
||||||
UserValidTypes::Create => {
|
PersonValidTypes::Create => {
|
||||||
receive_create(&context, any_base, actor_url, request_counter).await?
|
receive_create(&context, any_base, actor_url, request_counter).await?
|
||||||
}
|
}
|
||||||
UserValidTypes::Update => {
|
PersonValidTypes::Update => {
|
||||||
receive_update(&context, any_base, actor_url, request_counter).await?
|
receive_update(&context, any_base, actor_url, request_counter).await?
|
||||||
}
|
}
|
||||||
UserValidTypes::Delete => {
|
PersonValidTypes::Delete => {
|
||||||
receive_delete(context, any_base, &actor_url, request_counter).await?
|
receive_delete(context, any_base, &actor_url, request_counter).await?
|
||||||
}
|
}
|
||||||
UserValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?,
|
PersonValidTypes::Undo => receive_undo(context, any_base, &actor_url, request_counter).await?,
|
||||||
UserValidTypes::Remove => receive_remove_community(&context, any_base, &actor_url).await?,
|
PersonValidTypes::Remove => receive_remove_community(&context, any_base, &actor_url).await?,
|
||||||
};
|
};
|
||||||
|
|
||||||
// TODO: would be logical to move websocket notification code here
|
// TODO: would be logical to move websocket notification code here
|
||||||
|
@ -166,16 +173,16 @@ pub(crate) async fn user_receive_message(
|
||||||
Ok(HttpResponse::Ok().finish())
|
Ok(HttpResponse::Ok().finish())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the activity is addressed directly to one or more local users, or if it is
|
/// Returns true if the activity is addressed directly to one or more local persons, or if it is
|
||||||
/// addressed to the followers collection of a remote community, and at least one local user follows
|
/// addressed to the followers collection of a remote community, and at least one local person follows
|
||||||
/// it.
|
/// it.
|
||||||
async fn is_for_user_inbox(
|
async fn is_for_person_inbox(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
activity: &UserAcceptedActivities,
|
activity: &PersonAcceptedActivities,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let to_and_cc = get_activity_to_and_cc(activity);
|
let to_and_cc = get_activity_to_and_cc(activity);
|
||||||
// Check if it is addressed directly to any local user
|
// Check if it is addressed directly to any local person
|
||||||
if is_addressed_to_local_user(&to_and_cc, context.pool()).await? {
|
if is_addressed_to_local_person(&to_and_cc, context.pool()).await? {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -198,7 +205,7 @@ async fn is_for_user_inbox(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(anyhow!("Not addressed for any local user").into())
|
Err(anyhow!("Not addressed for any local person").into())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Handle accepted follows.
|
/// Handle accepted follows.
|
||||||
|
@ -206,7 +213,7 @@ async fn receive_accept(
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
activity: AnyBase,
|
activity: AnyBase,
|
||||||
actor: &dyn ActorType,
|
actor: &dyn ActorType,
|
||||||
user: User_,
|
person: Person,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError> {
|
) -> Result<(), LemmyError> {
|
||||||
let accept = Accept::from_any_base(activity)?.context(location_info!())?;
|
let accept = Accept::from_any_base(activity)?.context(location_info!())?;
|
||||||
|
@ -214,7 +221,7 @@ async fn receive_accept(
|
||||||
|
|
||||||
let object = accept.object().to_owned().one().context(location_info!())?;
|
let object = accept.object().to_owned().one().context(location_info!())?;
|
||||||
let follow = Follow::from_any_base(object)?.context(location_info!())?;
|
let follow = Follow::from_any_base(object)?.context(location_info!())?;
|
||||||
verify_activity_domains_valid(&follow, &user.actor_id(), false)?;
|
verify_activity_domains_valid(&follow, &person.actor_id(), false)?;
|
||||||
|
|
||||||
let community_uri = accept
|
let community_uri = accept
|
||||||
.actor()?
|
.actor()?
|
||||||
|
@ -226,10 +233,10 @@ async fn receive_accept(
|
||||||
get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?;
|
get_or_fetch_and_upsert_community(&community_uri, context, request_counter).await?;
|
||||||
|
|
||||||
let community_id = community.id;
|
let community_id = community.id;
|
||||||
let user_id = user.id;
|
let person_id = person.id;
|
||||||
// This will throw an error if no follow was requested
|
// This will throw an error if no follow was requested
|
||||||
blocking(&context.pool(), move |conn| {
|
blocking(&context.pool(), move |conn| {
|
||||||
CommunityFollower::follow_accepted(conn, community_id, user_id)
|
CommunityFollower::follow_accepted(conn, community_id, person_id)
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
|
|
|
@ -58,7 +58,7 @@ enum PageOrNote {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This file is for post/comment activities received by the community, and for post/comment
|
/// This file is for post/comment activities received by the community, and for post/comment
|
||||||
/// activities announced by the community and received by the user.
|
/// activities announced by the community and received by the person.
|
||||||
|
|
||||||
/// A post or comment being created
|
/// A post or comment being created
|
||||||
pub(in crate::inbox) async fn receive_create_for_community(
|
pub(in crate::inbox) async fn receive_create_for_community(
|
||||||
|
@ -120,9 +120,9 @@ pub(in crate::inbox) async fn receive_like_for_community(
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => receive_like_post(like, post, context, request_counter).await,
|
PostOrComment::Post(post) => receive_like_post(like, *post, context, request_counter).await,
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_like_comment(like, comment, context, request_counter).await
|
receive_like_comment(like, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -152,10 +152,10 @@ pub(in crate::inbox) async fn receive_dislike_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_dislike_post(dislike, post, context, request_counter).await
|
receive_dislike_post(dislike, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_dislike_comment(dislike, comment, context, request_counter).await
|
receive_dislike_comment(dislike, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -177,8 +177,8 @@ pub(in crate::inbox) async fn receive_delete_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_delete_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_delete_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_delete_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -215,8 +215,8 @@ pub(in crate::inbox) async fn receive_remove_for_community(
|
||||||
remove.id(community_id.domain().context(location_info!())?)?;
|
remove.id(community_id.domain().context(location_info!())?)?;
|
||||||
|
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_remove_post(context, remove, p).await,
|
Ok(PostOrComment::Post(p)) => receive_remove_post(context, remove, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_remove_comment(context, remove, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -276,8 +276,8 @@ pub(in crate::inbox) async fn receive_undo_delete_for_community(
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_undo_delete_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_undo_delete_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_undo_delete_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_undo_delete_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -300,8 +300,8 @@ pub(in crate::inbox) async fn receive_undo_remove_for_community(
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match find_post_or_comment_by_id(context, object).await {
|
match find_post_or_comment_by_id(context, object).await {
|
||||||
Ok(PostOrComment::Post(p)) => receive_undo_remove_post(context, p).await,
|
Ok(PostOrComment::Post(p)) => receive_undo_remove_post(context, *p).await,
|
||||||
Ok(PostOrComment::Comment(c)) => receive_undo_remove_comment(context, c).await,
|
Ok(PostOrComment::Comment(c)) => receive_undo_remove_comment(context, *c).await,
|
||||||
// if we dont have the object, no need to do anything
|
// if we dont have the object, no need to do anything
|
||||||
Err(_) => Ok(()),
|
Err(_) => Ok(()),
|
||||||
}
|
}
|
||||||
|
@ -325,10 +325,10 @@ pub(in crate::inbox) async fn receive_undo_like_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_undo_like_post(&like, post, context, request_counter).await
|
receive_undo_like_post(&like, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_undo_like_comment(&like, comment, context, request_counter).await
|
receive_undo_like_comment(&like, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -351,10 +351,10 @@ pub(in crate::inbox) async fn receive_undo_dislike_for_community(
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
match fetch_post_or_comment_by_id(&object_id, context, request_counter).await? {
|
||||||
PostOrComment::Post(post) => {
|
PostOrComment::Post(post) => {
|
||||||
receive_undo_dislike_post(&dislike, post, context, request_counter).await
|
receive_undo_dislike_post(&dislike, *post, context, request_counter).await
|
||||||
}
|
}
|
||||||
PostOrComment::Comment(comment) => {
|
PostOrComment::Comment(comment) => {
|
||||||
receive_undo_dislike_comment(&dislike, comment, context, request_counter).await
|
receive_undo_dislike_comment(&dislike, *comment, context, request_counter).await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -365,11 +365,11 @@ async fn fetch_post_or_comment_by_id(
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<PostOrComment, LemmyError> {
|
) -> Result<PostOrComment, LemmyError> {
|
||||||
if let Ok(post) = get_or_fetch_and_insert_post(apub_id, context, request_counter).await {
|
if let Ok(post) = get_or_fetch_and_insert_post(apub_id, context, request_counter).await {
|
||||||
return Ok(PostOrComment::Post(post));
|
return Ok(PostOrComment::Post(Box::new(post)));
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Ok(comment) = get_or_fetch_and_insert_comment(apub_id, context, request_counter).await {
|
if let Ok(comment) = get_or_fetch_and_insert_comment(apub_id, context, request_counter).await {
|
||||||
return Ok(PostOrComment::Comment(comment));
|
return Ok(PostOrComment::Comment(Box::new(comment)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
|
|
|
@ -7,8 +7,8 @@ use crate::{
|
||||||
inbox_verify_http_signature,
|
inbox_verify_http_signature,
|
||||||
is_activity_already_known,
|
is_activity_already_known,
|
||||||
is_addressed_to_community_followers,
|
is_addressed_to_community_followers,
|
||||||
is_addressed_to_local_user,
|
is_addressed_to_local_person,
|
||||||
user_inbox::{user_receive_message, UserAcceptedActivities},
|
person_inbox::{person_receive_message, PersonAcceptedActivities},
|
||||||
},
|
},
|
||||||
insert_activity,
|
insert_activity,
|
||||||
};
|
};
|
||||||
|
@ -69,9 +69,9 @@ pub async fn shared_inbox(
|
||||||
let mut res: Option<HttpResponse> = None;
|
let mut res: Option<HttpResponse> = None;
|
||||||
let to_and_cc = get_activity_to_and_cc(&activity);
|
let to_and_cc = get_activity_to_and_cc(&activity);
|
||||||
// Handle community first, so in case the sender is banned by the community, it will error out.
|
// Handle community first, so in case the sender is banned by the community, it will error out.
|
||||||
// If we handled the user receive first, the activity would be inserted to the database before the
|
// If we handled the person receive first, the activity would be inserted to the database before the
|
||||||
// community could check for bans.
|
// community could check for bans.
|
||||||
// Note that an activity can be addressed to a community and to a user (or multiple users) at the
|
// Note that an activity can be addressed to a community and to a person (or multiple persons) at the
|
||||||
// same time. In this case we still only handle it once, to avoid duplicate websocket
|
// same time. In this case we still only handle it once, to avoid duplicate websocket
|
||||||
// notifications.
|
// notifications.
|
||||||
let community = extract_local_community_from_destinations(&to_and_cc, context.pool()).await?;
|
let community = extract_local_community_from_destinations(&to_and_cc, context.pool()).await?;
|
||||||
|
@ -88,13 +88,13 @@ pub async fn shared_inbox(
|
||||||
)
|
)
|
||||||
.await?,
|
.await?,
|
||||||
);
|
);
|
||||||
} else if is_addressed_to_local_user(&to_and_cc, context.pool()).await? {
|
} else if is_addressed_to_local_person(&to_and_cc, context.pool()).await? {
|
||||||
let user_activity = UserAcceptedActivities::from_any_base(activity_any_base.clone())?
|
let person_activity = PersonAcceptedActivities::from_any_base(activity_any_base.clone())?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
// `to_user` is only used for follow activities (which we dont receive here), so no need to pass
|
// `to_person` is only used for follow activities (which we dont receive here), so no need to pass
|
||||||
// it in
|
// it in
|
||||||
user_receive_message(
|
person_receive_message(
|
||||||
user_activity,
|
person_activity,
|
||||||
None,
|
None,
|
||||||
actor.as_ref(),
|
actor.as_ref(),
|
||||||
&context,
|
&context,
|
||||||
|
@ -105,11 +105,11 @@ pub async fn shared_inbox(
|
||||||
.await?
|
.await?
|
||||||
.is_some()
|
.is_some()
|
||||||
{
|
{
|
||||||
let user_activity = UserAcceptedActivities::from_any_base(activity_any_base.clone())?
|
let person_activity = PersonAcceptedActivities::from_any_base(activity_any_base.clone())?
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
res = Some(
|
res = Some(
|
||||||
user_receive_message(
|
person_receive_message(
|
||||||
user_activity,
|
person_activity,
|
||||||
None,
|
None,
|
||||||
actor.as_ref(),
|
actor.as_ref(),
|
||||||
&context,
|
&context,
|
||||||
|
|
|
@ -26,13 +26,16 @@ use anyhow::{anyhow, Context};
|
||||||
use diesel::NotFound;
|
use diesel::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{source::activity::Activity_, ApubObject, DbPool};
|
use lemmy_db_queries::{source::activity::Activity_, ApubObject, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
activity::Activity,
|
source::{
|
||||||
comment::Comment,
|
activity::Activity,
|
||||||
community::Community,
|
comment::Comment,
|
||||||
post::Post,
|
community::Community,
|
||||||
private_message::PrivateMessage,
|
person::Person as DbPerson,
|
||||||
user::User_,
|
post::Post,
|
||||||
|
private_message::PrivateMessage,
|
||||||
|
},
|
||||||
|
DbUrl,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
use lemmy_utils::{location_info, settings::structs::Settings, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -42,7 +45,7 @@ use url::{ParseError, Url};
|
||||||
|
|
||||||
/// Activitystreams type for community
|
/// Activitystreams type for community
|
||||||
type GroupExt = Ext2<ApActor<ApObject<Group>>, GroupExtension, PublicKeyExtension>;
|
type GroupExt = Ext2<ApActor<ApObject<Group>>, GroupExtension, PublicKeyExtension>;
|
||||||
/// Activitystreams type for user
|
/// Activitystreams type for person
|
||||||
type PersonExt = Ext1<ApActor<ApObject<Person>>, PublicKeyExtension>;
|
type PersonExt = Ext1<ApActor<ApObject<Person>>, PublicKeyExtension>;
|
||||||
/// Activitystreams type for post
|
/// Activitystreams type for post
|
||||||
type PageExt = Ext1<ApObject<Page>, PageExtension>;
|
type PageExt = Ext1<ApObject<Page>, PageExtension>;
|
||||||
|
@ -118,27 +121,41 @@ fn check_is_apub_id_valid(apub_id: &Url) -> Result<(), LemmyError> {
|
||||||
/// and actors in Lemmy.
|
/// and actors in Lemmy.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait ApubObjectType {
|
pub trait ApubObjectType {
|
||||||
async fn send_create(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_create(&self, creator: &DbPerson, context: &LemmyContext)
|
||||||
async fn send_update(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
-> Result<(), LemmyError>;
|
||||||
async fn send_delete(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_update(&self, creator: &DbPerson, context: &LemmyContext)
|
||||||
|
-> Result<(), LemmyError>;
|
||||||
|
async fn send_delete(&self, creator: &DbPerson, context: &LemmyContext)
|
||||||
|
-> Result<(), LemmyError>;
|
||||||
async fn send_undo_delete(
|
async fn send_undo_delete(
|
||||||
&self,
|
&self,
|
||||||
creator: &User_,
|
creator: &DbPerson,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError>;
|
||||||
|
async fn send_remove(&self, mod_: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
|
async fn send_undo_remove(
|
||||||
|
&self,
|
||||||
|
mod_: &DbPerson,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
) -> Result<(), LemmyError>;
|
) -> Result<(), LemmyError>;
|
||||||
async fn send_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
async fn send_undo_remove(&self, mod_: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait ApubLikeableType {
|
pub trait ApubLikeableType {
|
||||||
async fn send_like(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_like(&self, creator: &DbPerson, context: &LemmyContext) -> Result<(), LemmyError>;
|
||||||
async fn send_dislike(&self, creator: &User_, context: &LemmyContext) -> Result<(), LemmyError>;
|
async fn send_dislike(
|
||||||
async fn send_undo_like(&self, creator: &User_, context: &LemmyContext)
|
&self,
|
||||||
-> Result<(), LemmyError>;
|
creator: &DbPerson,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError>;
|
||||||
|
async fn send_undo_like(
|
||||||
|
&self,
|
||||||
|
creator: &DbPerson,
|
||||||
|
context: &LemmyContext,
|
||||||
|
) -> Result<(), LemmyError>;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Common methods provided by ActivityPub actors (community and user). Not all methods are
|
/// Common methods provided by ActivityPub actors (community and person). Not all methods are
|
||||||
/// implemented by all actors.
|
/// implemented by all actors.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
pub trait ActorType {
|
pub trait ActorType {
|
||||||
|
@ -206,7 +223,7 @@ pub trait ActorType {
|
||||||
|
|
||||||
pub enum EndpointType {
|
pub enum EndpointType {
|
||||||
Community,
|
Community,
|
||||||
User,
|
Person,
|
||||||
Post,
|
Post,
|
||||||
Comment,
|
Comment,
|
||||||
PrivateMessage,
|
PrivateMessage,
|
||||||
|
@ -216,10 +233,10 @@ pub enum EndpointType {
|
||||||
pub fn generate_apub_endpoint(
|
pub fn generate_apub_endpoint(
|
||||||
endpoint_type: EndpointType,
|
endpoint_type: EndpointType,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
) -> Result<DbUrl, ParseError> {
|
||||||
let point = match endpoint_type {
|
let point = match endpoint_type {
|
||||||
EndpointType::Community => "c",
|
EndpointType::Community => "c",
|
||||||
EndpointType::User => "u",
|
EndpointType::Person => "u",
|
||||||
EndpointType::Post => "post",
|
EndpointType::Post => "post",
|
||||||
EndpointType::Comment => "comment",
|
EndpointType::Comment => "comment",
|
||||||
EndpointType::PrivateMessage => "private_message",
|
EndpointType::PrivateMessage => "private_message",
|
||||||
|
@ -236,21 +253,15 @@ pub fn generate_apub_endpoint(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_followers_url(
|
pub fn generate_followers_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
|
||||||
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
|
Ok(Url::parse(&format!("{}/followers", actor_id))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_inbox_url(
|
pub fn generate_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, ParseError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, ParseError> {
|
|
||||||
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
|
Ok(Url::parse(&format!("{}/inbox", actor_id))?.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn generate_shared_inbox_url(
|
pub fn generate_shared_inbox_url(actor_id: &DbUrl) -> Result<DbUrl, LemmyError> {
|
||||||
actor_id: &lemmy_db_schema::Url,
|
|
||||||
) -> Result<lemmy_db_schema::Url, LemmyError> {
|
|
||||||
let actor_id = actor_id.clone().into_inner();
|
let actor_id = actor_id.clone().into_inner();
|
||||||
let url = format!(
|
let url = format!(
|
||||||
"{}://{}{}/inbox",
|
"{}://{}{}/inbox",
|
||||||
|
@ -277,7 +288,7 @@ pub(crate) async fn insert_activity<T>(
|
||||||
where
|
where
|
||||||
T: Serialize + std::fmt::Debug + Send + 'static,
|
T: Serialize + std::fmt::Debug + Send + 'static,
|
||||||
{
|
{
|
||||||
let ap_id = ap_id.to_string();
|
let ap_id = ap_id.to_owned().into();
|
||||||
blocking(pool, move |conn| {
|
blocking(pool, move |conn| {
|
||||||
Activity::insert(conn, ap_id, &activity, local, sensitive)
|
Activity::insert(conn, ap_id, &activity, local, sensitive)
|
||||||
})
|
})
|
||||||
|
@ -286,8 +297,8 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum PostOrComment {
|
pub(crate) enum PostOrComment {
|
||||||
Comment(Comment),
|
Comment(Box<Comment>),
|
||||||
Post(Post),
|
Post(Box<Post>),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to find a post or comment in the local database, without any network requests.
|
/// Tries to find a post or comment in the local database, without any network requests.
|
||||||
|
@ -303,7 +314,7 @@ pub(crate) async fn find_post_or_comment_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(p) = post {
|
if let Ok(p) = post {
|
||||||
return Ok(PostOrComment::Post(p));
|
return Ok(PostOrComment::Post(Box::new(p)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
|
@ -312,18 +323,18 @@ pub(crate) async fn find_post_or_comment_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(c) = comment {
|
if let Ok(c) = comment {
|
||||||
return Ok(PostOrComment::Comment(c));
|
return Ok(PostOrComment::Comment(Box::new(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) enum Object {
|
pub(crate) enum Object {
|
||||||
Comment(Comment),
|
Comment(Box<Comment>),
|
||||||
Post(Post),
|
Post(Box<Post>),
|
||||||
Community(Community),
|
Community(Box<Community>),
|
||||||
User(User_),
|
Person(Box<DbPerson>),
|
||||||
PrivateMessage(PrivateMessage),
|
PrivateMessage(Box<PrivateMessage>),
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn find_object_by_id(
|
pub(crate) async fn find_object_by_id(
|
||||||
|
@ -333,18 +344,18 @@ pub(crate) async fn find_object_by_id(
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
if let Ok(pc) = find_post_or_comment_by_id(context, ap_id.to_owned()).await {
|
||||||
return Ok(match pc {
|
return Ok(match pc {
|
||||||
PostOrComment::Post(p) => Object::Post(p),
|
PostOrComment::Post(p) => Object::Post(Box::new(*p)),
|
||||||
PostOrComment::Comment(c) => Object::Comment(c),
|
PostOrComment::Comment(c) => Object::Comment(Box::new(*c)),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::read_from_apub_id(conn, &ap_id.into())
|
DbPerson::read_from_apub_id(conn, &ap_id.into())
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(u) = user {
|
if let Ok(u) = person {
|
||||||
return Ok(Object::User(u));
|
return Ok(Object::Person(Box::new(u)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let ap_id = apub_id.clone();
|
let ap_id = apub_id.clone();
|
||||||
|
@ -353,7 +364,7 @@ pub(crate) async fn find_object_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(c) = community {
|
if let Ok(c) = community {
|
||||||
return Ok(Object::Community(c));
|
return Ok(Object::Community(Box::new(c)));
|
||||||
}
|
}
|
||||||
|
|
||||||
let private_message = blocking(context.pool(), move |conn| {
|
let private_message = blocking(context.pool(), move |conn| {
|
||||||
|
@ -361,7 +372,7 @@ pub(crate) async fn find_object_by_id(
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
if let Ok(pm) = private_message {
|
if let Ok(pm) = private_message {
|
||||||
return Ok(Object::PrivateMessage(pm));
|
return Ok(Object::PrivateMessage(Box::new(pm)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(NotFound.into())
|
Err(NotFound.into())
|
||||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
||||||
check_object_for_community_or_site_ban,
|
check_object_for_community_or_site_ban,
|
||||||
create_tombstone,
|
create_tombstone,
|
||||||
get_object_from_apub,
|
get_object_from_apub,
|
||||||
get_or_fetch_and_upsert_user,
|
get_or_fetch_and_upsert_person,
|
||||||
get_source_markdown_value,
|
get_source_markdown_value,
|
||||||
set_content_and_source,
|
set_content_and_source,
|
||||||
FromApub,
|
FromApub,
|
||||||
|
@ -23,10 +23,13 @@ use activitystreams::{
|
||||||
use anyhow::{anyhow, Context};
|
use anyhow::{anyhow, Context};
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
comment::{Comment, CommentForm},
|
source::{
|
||||||
post::Post,
|
comment::{Comment, CommentForm},
|
||||||
user::User_,
|
person::Person,
|
||||||
|
post::Post,
|
||||||
|
},
|
||||||
|
CommentId,
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
|
@ -44,7 +47,7 @@ impl ToApub for Comment {
|
||||||
let mut comment = ApObject::new(Note::new());
|
let mut comment = ApObject::new(Note::new());
|
||||||
|
|
||||||
let creator_id = self.creator_id;
|
let creator_id = self.creator_id;
|
||||||
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
|
let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
|
||||||
|
|
||||||
let post_id = self.post_id;
|
let post_id = self.post_id;
|
||||||
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
let post = blocking(pool, move |conn| Post::read(conn, post_id)).await??;
|
||||||
|
@ -135,7 +138,8 @@ impl FromApubToForm<NoteExt> for CommentForm {
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let creator = get_or_fetch_and_upsert_user(creator_actor_id, context, request_counter).await?;
|
let creator =
|
||||||
|
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
|
||||||
|
|
||||||
let mut in_reply_tos = note
|
let mut in_reply_tos = note
|
||||||
.in_reply_to()
|
.in_reply_to()
|
||||||
|
@ -152,7 +156,7 @@ impl FromApubToForm<NoteExt> for CommentForm {
|
||||||
|
|
||||||
// The 2nd item, if it exists, is the parent comment apub_id
|
// The 2nd item, if it exists, is the parent comment apub_id
|
||||||
// For deeply nested comments, FromApub automatically gets called recursively
|
// For deeply nested comments, FromApub automatically gets called recursively
|
||||||
let parent_id: Option<i32> = match in_reply_tos.next() {
|
let parent_id: Option<CommentId> = match in_reply_tos.next() {
|
||||||
Some(parent_comment_uri) => {
|
Some(parent_comment_uri) => {
|
||||||
let parent_comment_ap_id = &parent_comment_uri?;
|
let parent_comment_ap_id = &parent_comment_uri?;
|
||||||
let parent_comment =
|
let parent_comment =
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
extensions::{context::lemmy_context, group_extensions::GroupExtension},
|
extensions::{context::lemmy_context, group_extensions::GroupExtension},
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
objects::{
|
objects::{
|
||||||
check_object_domain,
|
check_object_domain,
|
||||||
create_tombstone,
|
create_tombstone,
|
||||||
|
@ -73,13 +73,13 @@ impl ToApub for Community {
|
||||||
|
|
||||||
if let Some(icon_url) = &self.icon {
|
if let Some(icon_url) = &self.icon {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(icon_url)?);
|
image.set_url::<Url>(icon_url.to_owned().into());
|
||||||
group.set_icon(image.into_any_base()?);
|
group.set_icon(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(banner_url) = &self.banner {
|
if let Some(banner_url) = &self.banner {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(banner_url)?);
|
image.set_url::<Url>(banner_url.to_owned().into());
|
||||||
group.set_image(image.into_any_base()?);
|
group.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +143,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
||||||
.as_xsd_any_uri()
|
.as_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let creator = get_or_fetch_and_upsert_user(creator_uri, context, request_counter).await?;
|
let creator = get_or_fetch_and_upsert_person(creator_uri, context, request_counter).await?;
|
||||||
let name = group
|
let name = group
|
||||||
.inner
|
.inner
|
||||||
.preferred_username()
|
.preferred_username()
|
||||||
|
@ -173,7 +173,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|u| u.to_owned().into()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -185,7 +185,7 @@ impl FromApubToForm<GroupExt> for CommunityForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|u| u.to_owned().into()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
fetcher::{community::get_or_fetch_and_upsert_community, user::get_or_fetch_and_upsert_user},
|
fetcher::{community::get_or_fetch_and_upsert_community, person::get_or_fetch_and_upsert_person},
|
||||||
inbox::community_inbox::check_community_or_site_ban,
|
inbox::community_inbox::check_community_or_site_ban,
|
||||||
};
|
};
|
||||||
use activitystreams::{
|
use activitystreams::{
|
||||||
|
@ -14,7 +14,7 @@ use chrono::NaiveDateTime;
|
||||||
use diesel::result::Error::NotFound;
|
use diesel::result::Error::NotFound;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{ApubObject, Crud, DbPool};
|
use lemmy_db_queries::{ApubObject, Crud, DbPool};
|
||||||
use lemmy_db_schema::source::community::Community;
|
use lemmy_db_schema::{source::community::Community, CommunityId, DbUrl};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
settings::structs::Settings,
|
settings::structs::Settings,
|
||||||
|
@ -26,9 +26,9 @@ use url::Url;
|
||||||
|
|
||||||
pub(crate) mod comment;
|
pub(crate) mod comment;
|
||||||
pub(crate) mod community;
|
pub(crate) mod community;
|
||||||
|
pub(crate) mod person;
|
||||||
pub(crate) mod post;
|
pub(crate) mod post;
|
||||||
pub(crate) mod private_message;
|
pub(crate) mod private_message;
|
||||||
pub(crate) mod user;
|
|
||||||
|
|
||||||
/// Trait for converting an object or actor into the respective ActivityPub type.
|
/// Trait for converting an object or actor into the respective ActivityPub type.
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
|
@ -96,7 +96,7 @@ where
|
||||||
pub(in crate::objects) fn check_object_domain<T, Kind>(
|
pub(in crate::objects) fn check_object_domain<T, Kind>(
|
||||||
apub: &T,
|
apub: &T,
|
||||||
expected_domain: Url,
|
expected_domain: Url,
|
||||||
) -> Result<lemmy_db_schema::Url, LemmyError>
|
) -> Result<DbUrl, LemmyError>
|
||||||
where
|
where
|
||||||
T: Base + AsBase<Kind>,
|
T: Base + AsBase<Kind>,
|
||||||
{
|
{
|
||||||
|
@ -172,7 +172,7 @@ pub(in crate::objects) fn check_is_markdown(mime: Option<&Mime>) -> Result<(), L
|
||||||
/// Converts an ActivityPub object (eg `Note`) to a database object (eg `Comment`). If an object
|
/// Converts an ActivityPub object (eg `Note`) to a database object (eg `Comment`). If an object
|
||||||
/// with the same ActivityPub ID already exists in the database, it is returned directly. Otherwise
|
/// with the same ActivityPub ID already exists in the database, it is returned directly. Otherwise
|
||||||
/// the apub object is parsed, inserted and returned.
|
/// the apub object is parsed, inserted and returned.
|
||||||
pub(in crate::objects) async fn get_object_from_apub<From, Kind, To, ToForm>(
|
pub(in crate::objects) async fn get_object_from_apub<From, Kind, To, ToForm, IdType>(
|
||||||
from: &From,
|
from: &From,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: Url,
|
expected_domain: Url,
|
||||||
|
@ -180,7 +180,7 @@ pub(in crate::objects) async fn get_object_from_apub<From, Kind, To, ToForm>(
|
||||||
) -> Result<To, LemmyError>
|
) -> Result<To, LemmyError>
|
||||||
where
|
where
|
||||||
From: BaseExt<Kind>,
|
From: BaseExt<Kind>,
|
||||||
To: ApubObject<ToForm> + Crud<ToForm> + Send + 'static,
|
To: ApubObject<ToForm> + Crud<ToForm, IdType> + Send + 'static,
|
||||||
ToForm: FromApubToForm<From> + Send + 'static,
|
ToForm: FromApubToForm<From> + Send + 'static,
|
||||||
{
|
{
|
||||||
let object_id = from.id_unchecked().context(location_info!())?.to_owned();
|
let object_id = from.id_unchecked().context(location_info!())?.to_owned();
|
||||||
|
@ -205,20 +205,20 @@ where
|
||||||
|
|
||||||
pub(in crate::objects) async fn check_object_for_community_or_site_ban<T, Kind>(
|
pub(in crate::objects) async fn check_object_for_community_or_site_ban<T, Kind>(
|
||||||
object: &T,
|
object: &T,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<(), LemmyError>
|
) -> Result<(), LemmyError>
|
||||||
where
|
where
|
||||||
T: ObjectExt<Kind>,
|
T: ObjectExt<Kind>,
|
||||||
{
|
{
|
||||||
let user_id = object
|
let person_id = object
|
||||||
.attributed_to()
|
.attributed_to()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let user = get_or_fetch_and_upsert_user(user_id, context, request_counter).await?;
|
let person = get_or_fetch_and_upsert_person(person_id, context, request_counter).await?;
|
||||||
check_community_or_site_ban(&user, community_id, context.pool()).await
|
check_community_or_site_ban(&person, community_id, context.pool()).await
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(in crate::objects) async fn get_to_community<T, Kind>(
|
pub(in crate::objects) async fn get_to_community<T, Kind>(
|
||||||
|
|
|
@ -22,7 +22,7 @@ use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{ApubObject, DbPool};
|
use lemmy_db_queries::{ApubObject, DbPool};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::user::{UserForm, User_},
|
source::person::{Person as DbPerson, PersonForm},
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
|
@ -34,7 +34,7 @@ use lemmy_websocket::LemmyContext;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl ToApub for User_ {
|
impl ToApub for DbPerson {
|
||||||
type ApubType = PersonExt;
|
type ApubType = PersonExt;
|
||||||
|
|
||||||
async fn to_apub(&self, _pool: &DbPool) -> Result<PersonExt, LemmyError> {
|
async fn to_apub(&self, _pool: &DbPool) -> Result<PersonExt, LemmyError> {
|
||||||
|
@ -50,13 +50,13 @@ impl ToApub for User_ {
|
||||||
|
|
||||||
if let Some(avatar_url) = &self.avatar {
|
if let Some(avatar_url) = &self.avatar {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(avatar_url)?);
|
image.set_url::<Url>(avatar_url.to_owned().into());
|
||||||
person.set_icon(image.into_any_base()?);
|
person.set_icon(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(banner_url) = &self.banner {
|
if let Some(banner_url) = &self.banner {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(banner_url)?);
|
image.set_url::<Url>(banner_url.to_owned().into());
|
||||||
person.set_image(image.into_any_base()?);
|
person.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ impl ToApub for User_ {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApub for User_ {
|
impl FromApub for DbPerson {
|
||||||
type ApubType = PersonExt;
|
type ApubType = PersonExt;
|
||||||
|
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
|
@ -93,26 +93,29 @@ impl FromApub for User_ {
|
||||||
context: &LemmyContext,
|
context: &LemmyContext,
|
||||||
expected_domain: Url,
|
expected_domain: Url,
|
||||||
request_counter: &mut i32,
|
request_counter: &mut i32,
|
||||||
) -> Result<User_, LemmyError> {
|
) -> Result<DbPerson, LemmyError> {
|
||||||
let user_id = person.id_unchecked().context(location_info!())?.to_owned();
|
let person_id = person.id_unchecked().context(location_info!())?.to_owned();
|
||||||
let domain = user_id.domain().context(location_info!())?;
|
let domain = person_id.domain().context(location_info!())?;
|
||||||
if domain == Settings::get().hostname() {
|
if domain == Settings::get().hostname() {
|
||||||
let user = blocking(context.pool(), move |conn| {
|
let person = blocking(context.pool(), move |conn| {
|
||||||
User_::read_from_apub_id(conn, &user_id.into())
|
DbPerson::read_from_apub_id(conn, &person_id.into())
|
||||||
})
|
})
|
||||||
.await??;
|
.await??;
|
||||||
Ok(user)
|
Ok(person)
|
||||||
} else {
|
} else {
|
||||||
let user_form =
|
let person_form =
|
||||||
UserForm::from_apub(person, context, expected_domain, request_counter).await?;
|
PersonForm::from_apub(person, context, expected_domain, request_counter).await?;
|
||||||
let user = blocking(context.pool(), move |conn| User_::upsert(conn, &user_form)).await??;
|
let person = blocking(context.pool(), move |conn| {
|
||||||
Ok(user)
|
DbPerson::upsert(conn, &person_form)
|
||||||
|
})
|
||||||
|
.await??;
|
||||||
|
Ok(person)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait::async_trait(?Send)]
|
#[async_trait::async_trait(?Send)]
|
||||||
impl FromApubToForm<PersonExt> for UserForm {
|
impl FromApubToForm<PersonExt> for PersonForm {
|
||||||
async fn from_apub(
|
async fn from_apub(
|
||||||
person: &PersonExt,
|
person: &PersonExt,
|
||||||
_context: &LemmyContext,
|
_context: &LemmyContext,
|
||||||
|
@ -126,7 +129,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -139,7 +142,7 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
),
|
),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
|
@ -167,30 +170,20 @@ impl FromApubToForm<PersonExt> for UserForm {
|
||||||
check_slurs_opt(&preferred_username)?;
|
check_slurs_opt(&preferred_username)?;
|
||||||
check_slurs_opt(&bio)?;
|
check_slurs_opt(&bio)?;
|
||||||
|
|
||||||
Ok(UserForm {
|
Ok(PersonForm {
|
||||||
name,
|
name,
|
||||||
preferred_username: Some(preferred_username),
|
preferred_username: Some(preferred_username),
|
||||||
password_encrypted: "".to_string(),
|
|
||||||
admin: false,
|
|
||||||
banned: None,
|
banned: None,
|
||||||
email: None,
|
deleted: None,
|
||||||
avatar,
|
avatar: avatar.map(|o| o.map(|i| i.into())),
|
||||||
banner,
|
banner: banner.map(|o| o.map(|i| i.into())),
|
||||||
published: person.inner.published().map(|u| u.to_owned().naive_local()),
|
published: person.inner.published().map(|u| u.to_owned().naive_local()),
|
||||||
updated: person.updated().map(|u| u.to_owned().naive_local()),
|
updated: person.updated().map(|u| u.to_owned().naive_local()),
|
||||||
show_nsfw: false,
|
|
||||||
theme: "".to_string(),
|
|
||||||
default_sort_type: 0,
|
|
||||||
default_listing_type: 0,
|
|
||||||
lang: "".to_string(),
|
|
||||||
show_avatars: false,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
matrix_user_id: None,
|
|
||||||
actor_id: Some(check_object_domain(person, expected_domain)?),
|
actor_id: Some(check_object_domain(person, expected_domain)?),
|
||||||
bio: Some(bio),
|
bio: Some(bio),
|
||||||
local: false,
|
local: Some(false),
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: Some(person.ext_one.public_key.to_owned().public_key_pem),
|
public_key: Some(Some(person.ext_one.public_key.to_owned().public_key_pem)),
|
||||||
last_refreshed_at: Some(naive_now()),
|
last_refreshed_at: Some(naive_now()),
|
||||||
inbox_url: Some(person.inner.inbox()?.to_owned().into()),
|
inbox_url: Some(person.inner.inbox()?.to_owned().into()),
|
||||||
shared_inbox_url: Some(shared_inbox),
|
shared_inbox_url: Some(shared_inbox),
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
extensions::{context::lemmy_context, page_extension::PageExtension},
|
extensions::{context::lemmy_context, page_extension::PageExtension},
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
objects::{
|
objects::{
|
||||||
check_object_domain,
|
check_object_domain,
|
||||||
check_object_for_community_or_site_ban,
|
check_object_for_community_or_site_ban,
|
||||||
|
@ -24,10 +24,13 @@ use activitystreams_ext::Ext1;
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::{
|
||||||
community::Community,
|
self,
|
||||||
post::{Post, PostForm},
|
source::{
|
||||||
user::User_,
|
community::Community,
|
||||||
|
person::Person,
|
||||||
|
post::{Post, PostForm},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
use lemmy_utils::{
|
use lemmy_utils::{
|
||||||
location_info,
|
location_info,
|
||||||
|
@ -47,7 +50,7 @@ impl ToApub for Post {
|
||||||
let mut page = ApObject::new(Page::new());
|
let mut page = ApObject::new(Page::new());
|
||||||
|
|
||||||
let creator_id = self.creator_id;
|
let creator_id = self.creator_id;
|
||||||
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
|
let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
|
||||||
|
|
||||||
let community_id = self.community_id;
|
let community_id = self.community_id;
|
||||||
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
|
let community = blocking(pool, move |conn| Community::read(conn, community_id)).await??;
|
||||||
|
@ -70,16 +73,13 @@ impl ToApub for Post {
|
||||||
set_content_and_source(&mut page, &body)?;
|
set_content_and_source(&mut page, &body)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: hacky code because we get self.url == Some("")
|
if let Some(url) = &self.url {
|
||||||
// https://github.com/LemmyNet/lemmy/issues/602
|
page.set_url::<Url>(url.to_owned().into());
|
||||||
let url = self.url.as_ref().filter(|u| !u.is_empty());
|
|
||||||
if let Some(u) = url {
|
|
||||||
page.set_url(Url::parse(u)?);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(thumbnail_url) = &self.thumbnail_url {
|
if let Some(thumbnail_url) = &self.thumbnail_url {
|
||||||
let mut image = Image::new();
|
let mut image = Image::new();
|
||||||
image.set_url(Url::parse(thumbnail_url)?);
|
image.set_url::<Url>(thumbnail_url.to_owned().into());
|
||||||
page.set_image(image.into_any_base()?);
|
page.set_image(image.into_any_base()?);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +142,12 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let creator = get_or_fetch_and_upsert_user(creator_actor_id, context, request_counter).await?;
|
let creator =
|
||||||
|
get_or_fetch_and_upsert_person(creator_actor_id, context, request_counter).await?;
|
||||||
|
|
||||||
let community = get_to_community(page, context, request_counter).await?;
|
let community = get_to_community(page, context, request_counter).await?;
|
||||||
|
|
||||||
let thumbnail_url = match &page.inner.image() {
|
let thumbnail_url: Option<Url> = match &page.inner.image() {
|
||||||
Some(any_image) => Image::from_any_base(
|
Some(any_image) => Image::from_any_base(
|
||||||
any_image
|
any_image
|
||||||
.to_owned()
|
.to_owned()
|
||||||
|
@ -158,7 +159,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
.url()
|
.url()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
.as_single_xsd_any_uri()
|
.as_single_xsd_any_uri()
|
||||||
.map(|u| u.to_string()),
|
.map(|url| url.to_owned()),
|
||||||
None => None,
|
None => None,
|
||||||
};
|
};
|
||||||
let url = page
|
let url = page
|
||||||
|
@ -166,11 +167,11 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
.url()
|
.url()
|
||||||
.map(|u| u.as_single_xsd_any_uri())
|
.map(|u| u.as_single_xsd_any_uri())
|
||||||
.flatten()
|
.flatten()
|
||||||
.map(|s| s.to_string());
|
.map(|u| u.to_owned());
|
||||||
|
|
||||||
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
let (iframely_title, iframely_description, iframely_html, pictrs_thumbnail) =
|
||||||
if let Some(url) = &url {
|
if let Some(url) = &url {
|
||||||
fetch_iframely_and_pictrs_data(context.client(), Some(url.to_owned())).await
|
fetch_iframely_and_pictrs_data(context.client(), Some(url)).await
|
||||||
} else {
|
} else {
|
||||||
(None, None, None, thumbnail_url)
|
(None, None, None, thumbnail_url)
|
||||||
};
|
};
|
||||||
|
@ -192,7 +193,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
let body_slurs_removed = body.map(|b| remove_slurs(&b));
|
let body_slurs_removed = body.map(|b| remove_slurs(&b));
|
||||||
Ok(PostForm {
|
Ok(PostForm {
|
||||||
name,
|
name,
|
||||||
url,
|
url: url.map(|u| u.into()),
|
||||||
body: body_slurs_removed,
|
body: body_slurs_removed,
|
||||||
creator_id: creator.id,
|
creator_id: creator.id,
|
||||||
community_id: community.id,
|
community_id: community.id,
|
||||||
|
@ -214,7 +215,7 @@ impl FromApubToForm<PageExt> for PostForm {
|
||||||
embed_title: iframely_title,
|
embed_title: iframely_title,
|
||||||
embed_description: iframely_description,
|
embed_description: iframely_description,
|
||||||
embed_html: iframely_html,
|
embed_html: iframely_html,
|
||||||
thumbnail_url: pictrs_thumbnail,
|
thumbnail_url: pictrs_thumbnail.map(|u| u.into()),
|
||||||
ap_id: Some(check_object_domain(page, expected_domain)?),
|
ap_id: Some(check_object_domain(page, expected_domain)?),
|
||||||
local: false,
|
local: false,
|
||||||
})
|
})
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
check_is_apub_id_valid,
|
check_is_apub_id_valid,
|
||||||
extensions::context::lemmy_context,
|
extensions::context::lemmy_context,
|
||||||
fetcher::user::get_or_fetch_and_upsert_user,
|
fetcher::person::get_or_fetch_and_upsert_person,
|
||||||
objects::{
|
objects::{
|
||||||
check_object_domain,
|
check_object_domain,
|
||||||
create_tombstone,
|
create_tombstone,
|
||||||
|
@ -22,8 +22,8 @@ use anyhow::Context;
|
||||||
use lemmy_api_structs::blocking;
|
use lemmy_api_structs::blocking;
|
||||||
use lemmy_db_queries::{Crud, DbPool};
|
use lemmy_db_queries::{Crud, DbPool};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
|
person::Person,
|
||||||
private_message::{PrivateMessage, PrivateMessageForm},
|
private_message::{PrivateMessage, PrivateMessageForm},
|
||||||
user::User_,
|
|
||||||
};
|
};
|
||||||
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
|
use lemmy_utils::{location_info, utils::convert_datetime, LemmyError};
|
||||||
use lemmy_websocket::LemmyContext;
|
use lemmy_websocket::LemmyContext;
|
||||||
|
@ -37,10 +37,10 @@ impl ToApub for PrivateMessage {
|
||||||
let mut private_message = ApObject::new(Note::new());
|
let mut private_message = ApObject::new(Note::new());
|
||||||
|
|
||||||
let creator_id = self.creator_id;
|
let creator_id = self.creator_id;
|
||||||
let creator = blocking(pool, move |conn| User_::read(conn, creator_id)).await??;
|
let creator = blocking(pool, move |conn| Person::read(conn, creator_id)).await??;
|
||||||
|
|
||||||
let recipient_id = self.recipient_id;
|
let recipient_id = self.recipient_id;
|
||||||
let recipient = blocking(pool, move |conn| User_::read(conn, recipient_id)).await??;
|
let recipient = blocking(pool, move |conn| Person::read(conn, recipient_id)).await??;
|
||||||
|
|
||||||
private_message
|
private_message
|
||||||
.set_many_contexts(lemmy_context()?)
|
.set_many_contexts(lemmy_context()?)
|
||||||
|
@ -97,7 +97,8 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
|
|
||||||
let creator = get_or_fetch_and_upsert_user(&creator_actor_id, context, request_counter).await?;
|
let creator =
|
||||||
|
get_or_fetch_and_upsert_person(&creator_actor_id, context, request_counter).await?;
|
||||||
let recipient_actor_id = note
|
let recipient_actor_id = note
|
||||||
.to()
|
.to()
|
||||||
.context(location_info!())?
|
.context(location_info!())?
|
||||||
|
@ -105,7 +106,7 @@ impl FromApubToForm<NoteExt> for PrivateMessageForm {
|
||||||
.single_xsd_any_uri()
|
.single_xsd_any_uri()
|
||||||
.context(location_info!())?;
|
.context(location_info!())?;
|
||||||
let recipient =
|
let recipient =
|
||||||
get_or_fetch_and_upsert_user(&recipient_actor_id, context, request_counter).await?;
|
get_or_fetch_and_upsert_person(&recipient_actor_id, context, request_counter).await?;
|
||||||
let ap_id = note.id_unchecked().context(location_info!())?.to_string();
|
let ap_id = note.id_unchecked().context(location_info!())?.to_string();
|
||||||
check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
|
check_is_apub_id_valid(&Url::parse(&ap_id)?)?;
|
||||||
|
|
||||||
|
|
|
@ -8,10 +8,14 @@ use crate::{
|
||||||
get_apub_community_outbox,
|
get_apub_community_outbox,
|
||||||
},
|
},
|
||||||
get_activity,
|
get_activity,
|
||||||
|
person::{get_apub_person_http, get_apub_person_inbox, get_apub_person_outbox},
|
||||||
post::get_apub_post,
|
post::get_apub_post,
|
||||||
user::{get_apub_user_http, get_apub_user_inbox, get_apub_user_outbox},
|
|
||||||
},
|
},
|
||||||
inbox::{community_inbox::community_inbox, shared_inbox::shared_inbox, user_inbox::user_inbox},
|
inbox::{
|
||||||
|
community_inbox::community_inbox,
|
||||||
|
person_inbox::person_inbox,
|
||||||
|
shared_inbox::shared_inbox,
|
||||||
|
},
|
||||||
APUB_JSON_CONTENT_TYPE,
|
APUB_JSON_CONTENT_TYPE,
|
||||||
};
|
};
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
@ -53,9 +57,12 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
"/c/{community_name}/inbox",
|
"/c/{community_name}/inbox",
|
||||||
web::get().to(get_apub_community_inbox),
|
web::get().to(get_apub_community_inbox),
|
||||||
)
|
)
|
||||||
.route("/u/{user_name}", web::get().to(get_apub_user_http))
|
.route("/u/{user_name}", web::get().to(get_apub_person_http))
|
||||||
.route("/u/{user_name}/outbox", web::get().to(get_apub_user_outbox))
|
.route(
|
||||||
.route("/u/{user_name}/inbox", web::get().to(get_apub_user_inbox))
|
"/u/{user_name}/outbox",
|
||||||
|
web::get().to(get_apub_person_outbox),
|
||||||
|
)
|
||||||
|
.route("/u/{user_name}/inbox", web::get().to(get_apub_person_inbox))
|
||||||
.route("/post/{post_id}", web::get().to(get_apub_post))
|
.route("/post/{post_id}", web::get().to(get_apub_post))
|
||||||
.route("/comment/{comment_id}", web::get().to(get_apub_comment))
|
.route("/comment/{comment_id}", web::get().to(get_apub_comment))
|
||||||
.route("/activities/{type_}/{id}", web::get().to(get_activity)),
|
.route("/activities/{type_}/{id}", web::get().to(get_activity)),
|
||||||
|
@ -66,7 +73,7 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||||
.wrap(digest_verifier)
|
.wrap(digest_verifier)
|
||||||
.guard(header_guard_content_type)
|
.guard(header_guard_content_type)
|
||||||
.route("/c/{community_name}/inbox", web::post().to(community_inbox))
|
.route("/c/{community_name}/inbox", web::post().to(community_inbox))
|
||||||
.route("/u/{user_name}/inbox", web::post().to(user_inbox))
|
.route("/u/{user_name}/inbox", web::post().to(person_inbox))
|
||||||
.route("/inbox", web::post().to(shared_inbox)),
|
.route("/inbox", web::post().to(shared_inbox)),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ strum = "0.20.0"
|
||||||
strum_macros = "0.20.1"
|
strum_macros = "0.20.1"
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
sha2 = "0.9.3"
|
sha2 = "0.9.3"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
lazy_static = "1.4.0"
|
lazy_static = "1.4.0"
|
||||||
regex = "1.4.3"
|
regex = "1.4.3"
|
||||||
bcrypt = "0.9.0"
|
bcrypt = "0.9.0"
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::schema::comment_aggregates;
|
use lemmy_db_schema::{schema::comment_aggregates, CommentId};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||||
#[table_name = "comment_aggregates"]
|
#[table_name = "comment_aggregates"]
|
||||||
pub struct CommentAggregates {
|
pub struct CommentAggregates {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub score: i64,
|
pub score: i64,
|
||||||
pub upvotes: i64,
|
pub upvotes: i64,
|
||||||
pub downvotes: i64,
|
pub downvotes: i64,
|
||||||
|
@ -14,7 +14,7 @@ pub struct CommentAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommentAggregates {
|
impl CommentAggregates {
|
||||||
pub fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection, comment_id: CommentId) -> Result<Self, Error> {
|
||||||
comment_aggregates::table
|
comment_aggregates::table
|
||||||
.filter(comment_aggregates::comment_id.eq(comment_id))
|
.filter(comment_aggregates::comment_id.eq(comment_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
|
@ -28,14 +28,12 @@ mod tests {
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -44,28 +42,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy_comment_agg".into(),
|
name: "thommy_comment_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -73,30 +61,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let another_user = UserForm {
|
let another_person = PersonForm {
|
||||||
name: "jerry_comment_agg".into(),
|
name: "jerry_comment_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -104,11 +82,11 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let another_inserted_user = User_::create(&conn, &another_user).unwrap();
|
let another_inserted_person = Person::create(&conn, &another_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL_comment_agg".into(),
|
name: "TIL_comment_agg".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -134,7 +112,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -155,7 +133,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -171,7 +149,7 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_form = CommentForm {
|
let child_comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -188,7 +166,7 @@ mod tests {
|
||||||
let comment_like = CommentLikeForm {
|
let comment_like = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -200,11 +178,11 @@ mod tests {
|
||||||
assert_eq!(1, comment_aggs_before_delete.upvotes);
|
assert_eq!(1, comment_aggs_before_delete.upvotes);
|
||||||
assert_eq!(0, comment_aggs_before_delete.downvotes);
|
assert_eq!(0, comment_aggs_before_delete.downvotes);
|
||||||
|
|
||||||
// Add a post dislike from the other user
|
// Add a post dislike from the other person
|
||||||
let comment_dislike = CommentLikeForm {
|
let comment_dislike = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: another_inserted_user.id,
|
person_id: another_inserted_person.id,
|
||||||
score: -1,
|
score: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -217,7 +195,7 @@ mod tests {
|
||||||
assert_eq!(1, comment_aggs_after_dislike.downvotes);
|
assert_eq!(1, comment_aggs_after_dislike.downvotes);
|
||||||
|
|
||||||
// Remove the first comment like
|
// Remove the first comment like
|
||||||
CommentLike::remove(&conn, inserted_user.id, inserted_comment.id).unwrap();
|
CommentLike::remove(&conn, inserted_person.id, inserted_comment.id).unwrap();
|
||||||
let after_like_remove = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
|
let after_like_remove = CommentAggregates::read(&conn, inserted_comment.id).unwrap();
|
||||||
assert_eq!(-1, after_like_remove.score);
|
assert_eq!(-1, after_like_remove.score);
|
||||||
assert_eq!(0, after_like_remove.upvotes);
|
assert_eq!(0, after_like_remove.upvotes);
|
||||||
|
@ -231,8 +209,8 @@ mod tests {
|
||||||
assert!(after_delete.is_err());
|
assert!(after_delete.is_err());
|
||||||
|
|
||||||
// This should delete all the associated rows, and fire triggers
|
// This should delete all the associated rows, and fire triggers
|
||||||
User_::delete(&conn, another_inserted_user.id).unwrap();
|
Person::delete(&conn, another_inserted_person.id).unwrap();
|
||||||
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(1, user_num_deleted);
|
assert_eq!(1, person_num_deleted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::schema::community_aggregates;
|
use lemmy_db_schema::{schema::community_aggregates, CommunityId};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||||
#[table_name = "community_aggregates"]
|
#[table_name = "community_aggregates"]
|
||||||
pub struct CommunityAggregates {
|
pub struct CommunityAggregates {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub subscribers: i64,
|
pub subscribers: i64,
|
||||||
pub posts: i64,
|
pub posts: i64,
|
||||||
pub comments: i64,
|
pub comments: i64,
|
||||||
|
@ -18,7 +18,7 @@ pub struct CommunityAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommunityAggregates {
|
impl CommunityAggregates {
|
||||||
pub fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection, community_id: CommunityId) -> Result<Self, Error> {
|
||||||
community_aggregates::table
|
community_aggregates::table
|
||||||
.filter(community_aggregates::community_id.eq(community_id))
|
.filter(community_aggregates::community_id.eq(community_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
|
@ -32,14 +32,12 @@ mod tests {
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
Crud,
|
||||||
Followable,
|
Followable,
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
|
community::{Community, CommunityFollower, CommunityFollowerForm, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -48,28 +46,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy_community_agg".into(),
|
name: "thommy_community_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -77,30 +65,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let another_user = UserForm {
|
let another_person = PersonForm {
|
||||||
name: "jerry_community_agg".into(),
|
name: "jerry_community_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -108,11 +86,11 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let another_inserted_user = User_::create(&conn, &another_user).unwrap();
|
let another_inserted_person = Person::create(&conn, &another_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL_community_agg".into(),
|
name: "TIL_community_agg".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -136,7 +114,7 @@ mod tests {
|
||||||
|
|
||||||
let another_community = CommunityForm {
|
let another_community = CommunityForm {
|
||||||
name: "TIL_community_agg_2".into(),
|
name: "TIL_community_agg_2".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -158,25 +136,25 @@ mod tests {
|
||||||
|
|
||||||
let another_inserted_community = Community::create(&conn, &another_community).unwrap();
|
let another_inserted_community = Community::create(&conn, &another_community).unwrap();
|
||||||
|
|
||||||
let first_user_follow = CommunityFollowerForm {
|
let first_person_follow = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
CommunityFollower::follow(&conn, &first_user_follow).unwrap();
|
CommunityFollower::follow(&conn, &first_person_follow).unwrap();
|
||||||
|
|
||||||
let second_user_follow = CommunityFollowerForm {
|
let second_person_follow = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: another_inserted_user.id,
|
person_id: another_inserted_person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
CommunityFollower::follow(&conn, &second_user_follow).unwrap();
|
CommunityFollower::follow(&conn, &second_person_follow).unwrap();
|
||||||
|
|
||||||
let another_community_follow = CommunityFollowerForm {
|
let another_community_follow = CommunityFollowerForm {
|
||||||
community_id: another_inserted_community.id,
|
community_id: another_inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -186,7 +164,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -207,7 +185,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -223,7 +201,7 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_form = CommentForm {
|
let child_comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -252,12 +230,12 @@ mod tests {
|
||||||
assert_eq!(0, another_community_aggs.comments);
|
assert_eq!(0, another_community_aggs.comments);
|
||||||
|
|
||||||
// Unfollow test
|
// Unfollow test
|
||||||
CommunityFollower::unfollow(&conn, &second_user_follow).unwrap();
|
CommunityFollower::unfollow(&conn, &second_person_follow).unwrap();
|
||||||
let after_unfollow = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
let after_unfollow = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
||||||
assert_eq!(1, after_unfollow.subscribers);
|
assert_eq!(1, after_unfollow.subscribers);
|
||||||
|
|
||||||
// Follow again just for the later tests
|
// Follow again just for the later tests
|
||||||
CommunityFollower::follow(&conn, &second_user_follow).unwrap();
|
CommunityFollower::follow(&conn, &second_person_follow).unwrap();
|
||||||
let after_follow_again = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
let after_follow_again = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
||||||
assert_eq!(2, after_follow_again.subscribers);
|
assert_eq!(2, after_follow_again.subscribers);
|
||||||
|
|
||||||
|
@ -267,14 +245,14 @@ mod tests {
|
||||||
assert_eq!(0, after_parent_post_delete.comments);
|
assert_eq!(0, after_parent_post_delete.comments);
|
||||||
assert_eq!(0, after_parent_post_delete.posts);
|
assert_eq!(0, after_parent_post_delete.posts);
|
||||||
|
|
||||||
// Remove the 2nd user
|
// Remove the 2nd person
|
||||||
User_::delete(&conn, another_inserted_user.id).unwrap();
|
Person::delete(&conn, another_inserted_person.id).unwrap();
|
||||||
let after_user_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
let after_person_delete = CommunityAggregates::read(&conn, inserted_community.id).unwrap();
|
||||||
assert_eq!(1, after_user_delete.subscribers);
|
assert_eq!(1, after_person_delete.subscribers);
|
||||||
|
|
||||||
// This should delete all the associated rows, and fire triggers
|
// This should delete all the associated rows, and fire triggers
|
||||||
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(1, user_num_deleted);
|
assert_eq!(1, person_num_deleted);
|
||||||
|
|
||||||
// Should be none found, since the creator was deleted
|
// Should be none found, since the creator was deleted
|
||||||
let after_delete = CommunityAggregates::read(&conn, inserted_community.id);
|
let after_delete = CommunityAggregates::read(&conn, inserted_community.id);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
pub mod comment_aggregates;
|
pub mod comment_aggregates;
|
||||||
pub mod community_aggregates;
|
pub mod community_aggregates;
|
||||||
|
pub mod person_aggregates;
|
||||||
pub mod post_aggregates;
|
pub mod post_aggregates;
|
||||||
pub mod site_aggregates;
|
pub mod site_aggregates;
|
||||||
pub mod user_aggregates;
|
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::schema::user_aggregates;
|
use lemmy_db_schema::{schema::person_aggregates, PersonId};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||||
#[table_name = "user_aggregates"]
|
#[table_name = "person_aggregates"]
|
||||||
pub struct UserAggregates {
|
pub struct PersonAggregates {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub post_count: i64,
|
pub post_count: i64,
|
||||||
pub post_score: i64,
|
pub post_score: i64,
|
||||||
pub comment_count: i64,
|
pub comment_count: i64,
|
||||||
pub comment_score: i64,
|
pub comment_score: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserAggregates {
|
impl PersonAggregates {
|
||||||
pub fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
|
||||||
user_aggregates::table
|
person_aggregates::table
|
||||||
.filter(user_aggregates::user_id.eq(user_id))
|
.filter(person_aggregates::person_id.eq(person_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,16 @@ impl UserAggregates {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{
|
||||||
aggregates::user_aggregates::UserAggregates,
|
aggregates::person_aggregates::PersonAggregates,
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
comment::{Comment, CommentForm, CommentLike, CommentLikeForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm, PostLike, PostLikeForm},
|
post::{Post, PostForm, PostLike, PostLikeForm},
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -44,28 +42,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy_user_agg".into(),
|
name: "thommy_user_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -73,30 +61,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let another_user = UserForm {
|
let another_person = PersonForm {
|
||||||
name: "jerry_user_agg".into(),
|
name: "jerry_user_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -104,11 +82,11 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let another_inserted_user = User_::create(&conn, &another_user).unwrap();
|
let another_inserted_person = Person::create(&conn, &another_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL_site_agg".into(),
|
name: "TIL_site_agg".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -134,7 +112,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -155,7 +133,7 @@ mod tests {
|
||||||
|
|
||||||
let post_like = PostLikeForm {
|
let post_like = PostLikeForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -163,7 +141,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -179,7 +157,7 @@ mod tests {
|
||||||
|
|
||||||
let mut comment_like = CommentLikeForm {
|
let mut comment_like = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
@ -188,7 +166,7 @@ mod tests {
|
||||||
|
|
||||||
let mut child_comment_form = CommentForm {
|
let mut child_comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -204,28 +182,29 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_like = CommentLikeForm {
|
let child_comment_like = CommentLikeForm {
|
||||||
comment_id: inserted_child_comment.id,
|
comment_id: inserted_child_comment.id,
|
||||||
user_id: another_inserted_user.id,
|
person_id: another_inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap();
|
let _inserted_child_comment_like = CommentLike::like(&conn, &child_comment_like).unwrap();
|
||||||
|
|
||||||
let user_aggregates_before_delete = UserAggregates::read(&conn, inserted_user.id).unwrap();
|
let person_aggregates_before_delete =
|
||||||
|
PersonAggregates::read(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(1, user_aggregates_before_delete.post_count);
|
assert_eq!(1, person_aggregates_before_delete.post_count);
|
||||||
assert_eq!(1, user_aggregates_before_delete.post_score);
|
assert_eq!(1, person_aggregates_before_delete.post_score);
|
||||||
assert_eq!(2, user_aggregates_before_delete.comment_count);
|
assert_eq!(2, person_aggregates_before_delete.comment_count);
|
||||||
assert_eq!(2, user_aggregates_before_delete.comment_score);
|
assert_eq!(2, person_aggregates_before_delete.comment_score);
|
||||||
|
|
||||||
// Remove a post like
|
// Remove a post like
|
||||||
PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
|
PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
|
||||||
let after_post_like_remove = UserAggregates::read(&conn, inserted_user.id).unwrap();
|
let after_post_like_remove = PersonAggregates::read(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(0, after_post_like_remove.post_score);
|
assert_eq!(0, after_post_like_remove.post_score);
|
||||||
|
|
||||||
// Remove a parent comment (the scores should also be removed)
|
// Remove a parent comment (the scores should also be removed)
|
||||||
Comment::delete(&conn, inserted_comment.id).unwrap();
|
Comment::delete(&conn, inserted_comment.id).unwrap();
|
||||||
let after_parent_comment_delete = UserAggregates::read(&conn, inserted_user.id).unwrap();
|
let after_parent_comment_delete = PersonAggregates::read(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(0, after_parent_comment_delete.comment_count);
|
assert_eq!(0, after_parent_comment_delete.comment_count);
|
||||||
assert_eq!(0, after_parent_comment_delete.comment_score);
|
assert_eq!(0, after_parent_comment_delete.comment_score);
|
||||||
|
|
||||||
|
@ -235,24 +214,24 @@ mod tests {
|
||||||
Comment::create(&conn, &child_comment_form).unwrap();
|
Comment::create(&conn, &child_comment_form).unwrap();
|
||||||
comment_like.comment_id = new_parent_comment.id;
|
comment_like.comment_id = new_parent_comment.id;
|
||||||
CommentLike::like(&conn, &comment_like).unwrap();
|
CommentLike::like(&conn, &comment_like).unwrap();
|
||||||
let after_comment_add = UserAggregates::read(&conn, inserted_user.id).unwrap();
|
let after_comment_add = PersonAggregates::read(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(2, after_comment_add.comment_count);
|
assert_eq!(2, after_comment_add.comment_count);
|
||||||
assert_eq!(1, after_comment_add.comment_score);
|
assert_eq!(1, after_comment_add.comment_score);
|
||||||
|
|
||||||
Post::delete(&conn, inserted_post.id).unwrap();
|
Post::delete(&conn, inserted_post.id).unwrap();
|
||||||
let after_post_delete = UserAggregates::read(&conn, inserted_user.id).unwrap();
|
let after_post_delete = PersonAggregates::read(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(0, after_post_delete.comment_score);
|
assert_eq!(0, after_post_delete.comment_score);
|
||||||
assert_eq!(0, after_post_delete.comment_count);
|
assert_eq!(0, after_post_delete.comment_count);
|
||||||
assert_eq!(0, after_post_delete.post_score);
|
assert_eq!(0, after_post_delete.post_score);
|
||||||
assert_eq!(0, after_post_delete.post_count);
|
assert_eq!(0, after_post_delete.post_count);
|
||||||
|
|
||||||
// This should delete all the associated rows, and fire triggers
|
// This should delete all the associated rows, and fire triggers
|
||||||
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(1, user_num_deleted);
|
assert_eq!(1, person_num_deleted);
|
||||||
User_::delete(&conn, another_inserted_user.id).unwrap();
|
Person::delete(&conn, another_inserted_person.id).unwrap();
|
||||||
|
|
||||||
// Should be none found
|
// Should be none found
|
||||||
let after_delete = UserAggregates::read(&conn, inserted_user.id);
|
let after_delete = PersonAggregates::read(&conn, inserted_person.id);
|
||||||
assert!(after_delete.is_err());
|
assert!(after_delete.is_err());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,12 +1,12 @@
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::schema::post_aggregates;
|
use lemmy_db_schema::{schema::post_aggregates, PostId};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
#[derive(Queryable, Associations, Identifiable, PartialEq, Debug, Serialize, Clone)]
|
||||||
#[table_name = "post_aggregates"]
|
#[table_name = "post_aggregates"]
|
||||||
pub struct PostAggregates {
|
pub struct PostAggregates {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub comments: i64,
|
pub comments: i64,
|
||||||
pub score: i64,
|
pub score: i64,
|
||||||
pub upvotes: i64,
|
pub upvotes: i64,
|
||||||
|
@ -18,7 +18,7 @@ pub struct PostAggregates {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PostAggregates {
|
impl PostAggregates {
|
||||||
pub fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
|
pub fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
|
||||||
post_aggregates::table
|
post_aggregates::table
|
||||||
.filter(post_aggregates::post_id.eq(post_id))
|
.filter(post_aggregates::post_id.eq(post_id))
|
||||||
.first::<Self>(conn)
|
.first::<Self>(conn)
|
||||||
|
@ -32,14 +32,12 @@ mod tests {
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
Crud,
|
Crud,
|
||||||
Likeable,
|
Likeable,
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm, PostLike, PostLikeForm},
|
post::{Post, PostForm, PostLike, PostLikeForm},
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -48,28 +46,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy_community_agg".into(),
|
name: "thommy_community_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -77,30 +65,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let another_user = UserForm {
|
let another_person = PersonForm {
|
||||||
name: "jerry_community_agg".into(),
|
name: "jerry_community_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -108,11 +86,11 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let another_inserted_user = User_::create(&conn, &another_user).unwrap();
|
let another_inserted_person = Person::create(&conn, &another_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL_community_agg".into(),
|
name: "TIL_community_agg".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -138,7 +116,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -159,7 +137,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -175,7 +153,7 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_form = CommentForm {
|
let child_comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -191,7 +169,7 @@ mod tests {
|
||||||
|
|
||||||
let post_like = PostLikeForm {
|
let post_like = PostLikeForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -204,10 +182,10 @@ mod tests {
|
||||||
assert_eq!(1, post_aggs_before_delete.upvotes);
|
assert_eq!(1, post_aggs_before_delete.upvotes);
|
||||||
assert_eq!(0, post_aggs_before_delete.downvotes);
|
assert_eq!(0, post_aggs_before_delete.downvotes);
|
||||||
|
|
||||||
// Add a post dislike from the other user
|
// Add a post dislike from the other person
|
||||||
let post_dislike = PostLikeForm {
|
let post_dislike = PostLikeForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: another_inserted_user.id,
|
person_id: another_inserted_person.id,
|
||||||
score: -1,
|
score: -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -229,7 +207,7 @@ mod tests {
|
||||||
assert_eq!(1, after_comment_delete.downvotes);
|
assert_eq!(1, after_comment_delete.downvotes);
|
||||||
|
|
||||||
// Remove the first post like
|
// Remove the first post like
|
||||||
PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
|
PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
|
||||||
let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
|
let after_like_remove = PostAggregates::read(&conn, inserted_post.id).unwrap();
|
||||||
assert_eq!(0, after_like_remove.comments);
|
assert_eq!(0, after_like_remove.comments);
|
||||||
assert_eq!(-1, after_like_remove.score);
|
assert_eq!(-1, after_like_remove.score);
|
||||||
|
@ -237,9 +215,9 @@ mod tests {
|
||||||
assert_eq!(1, after_like_remove.downvotes);
|
assert_eq!(1, after_like_remove.downvotes);
|
||||||
|
|
||||||
// This should delete all the associated rows, and fire triggers
|
// This should delete all the associated rows, and fire triggers
|
||||||
User_::delete(&conn, another_inserted_user.id).unwrap();
|
Person::delete(&conn, another_inserted_person.id).unwrap();
|
||||||
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(1, user_num_deleted);
|
assert_eq!(1, person_num_deleted);
|
||||||
|
|
||||||
// Should be none found, since the creator was deleted
|
// Should be none found, since the creator was deleted
|
||||||
let after_delete = PostAggregates::read(&conn, inserted_post.id);
|
let after_delete = PostAggregates::read(&conn, inserted_post.id);
|
||||||
|
|
|
@ -25,19 +25,13 @@ impl SiteAggregates {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{aggregates::site_aggregates::SiteAggregates, establish_unpooled_connection, Crud};
|
||||||
aggregates::site_aggregates::SiteAggregates,
|
|
||||||
establish_unpooled_connection,
|
|
||||||
Crud,
|
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::{Comment, CommentForm},
|
comment::{Comment, CommentForm},
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::{Post, PostForm},
|
post::{Post, PostForm},
|
||||||
site::{Site, SiteForm},
|
site::{Site, SiteForm},
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -46,28 +40,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy_site_agg".into(),
|
name: "thommy_site_agg".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -75,14 +59,14 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let site_form = SiteForm {
|
let site_form = SiteForm {
|
||||||
name: "test_site".into(),
|
name: "test_site".into(),
|
||||||
description: None,
|
description: None,
|
||||||
icon: None,
|
icon: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
enable_downvotes: true,
|
enable_downvotes: true,
|
||||||
open_registration: true,
|
open_registration: true,
|
||||||
enable_nsfw: true,
|
enable_nsfw: true,
|
||||||
|
@ -93,7 +77,7 @@ mod tests {
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL_site_agg".into(),
|
name: "TIL_site_agg".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -119,7 +103,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -142,7 +126,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -159,7 +143,7 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_form = CommentForm {
|
let child_comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -187,8 +171,8 @@ mod tests {
|
||||||
assert_eq!(0, site_aggregates_after_post_delete.comments);
|
assert_eq!(0, site_aggregates_after_post_delete.comments);
|
||||||
|
|
||||||
// This shouuld delete all the associated rows, and fire triggers
|
// This shouuld delete all the associated rows, and fire triggers
|
||||||
let user_num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let person_num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
assert_eq!(1, user_num_deleted);
|
assert_eq!(1, person_num_deleted);
|
||||||
|
|
||||||
let after_delete = SiteAggregates::read(&conn);
|
let after_delete = SiteAggregates::read(&conn);
|
||||||
assert!(after_delete.is_err());
|
assert!(after_delete.is_err());
|
||||||
|
|
|
@ -13,27 +13,29 @@ extern crate diesel_migrations;
|
||||||
extern crate serial_test;
|
extern crate serial_test;
|
||||||
|
|
||||||
use diesel::{result::Error, *};
|
use diesel::{result::Error, *};
|
||||||
use lemmy_db_schema::Url;
|
use lemmy_db_schema::{CommunityId, DbUrl, PersonId};
|
||||||
|
use lemmy_utils::ApiError;
|
||||||
use regex::Regex;
|
use regex::Regex;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{env, env::VarError};
|
use std::{env, env::VarError};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod aggregates;
|
pub mod aggregates;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
|
|
||||||
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
pub type DbPool = diesel::r2d2::Pool<diesel::r2d2::ConnectionManager<diesel::PgConnection>>;
|
||||||
|
|
||||||
pub trait Crud<T> {
|
pub trait Crud<Form, IdType> {
|
||||||
fn create(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn create(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn read(conn: &PgConnection, id: i32) -> Result<Self, Error>
|
fn read(conn: &PgConnection, id: IdType) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn update(conn: &PgConnection, id: i32, form: &T) -> Result<Self, Error>
|
fn update(conn: &PgConnection, id: IdType, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn delete(_conn: &PgConnection, _id: i32) -> Result<usize, Error>
|
fn delete(_conn: &PgConnection, _id: IdType) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -41,81 +43,85 @@ pub trait Crud<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Followable<T> {
|
pub trait Followable<Form> {
|
||||||
fn follow(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn follow(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn follow_accepted(conn: &PgConnection, community_id: i32, user_id: i32) -> Result<Self, Error>
|
fn follow_accepted(
|
||||||
|
conn: &PgConnection,
|
||||||
|
community_id: CommunityId,
|
||||||
|
person_id: PersonId,
|
||||||
|
) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unfollow(conn: &PgConnection, form: &T) -> Result<usize, Error>
|
fn unfollow(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn has_local_followers(conn: &PgConnection, community_id: i32) -> Result<bool, Error>;
|
fn has_local_followers(conn: &PgConnection, community_id: CommunityId) -> Result<bool, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Joinable<T> {
|
pub trait Joinable<Form> {
|
||||||
fn join(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn join(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn leave(conn: &PgConnection, form: &T) -> Result<usize, Error>
|
fn leave(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Likeable<T> {
|
pub trait Likeable<Form, IdType> {
|
||||||
fn like(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn like(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn remove(conn: &PgConnection, user_id: i32, item_id: i32) -> Result<usize, Error>
|
fn remove(conn: &PgConnection, person_id: PersonId, item_id: IdType) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Bannable<T> {
|
pub trait Bannable<Form> {
|
||||||
fn ban(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn ban(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unban(conn: &PgConnection, form: &T) -> Result<usize, Error>
|
fn unban(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Saveable<T> {
|
pub trait Saveable<Form> {
|
||||||
fn save(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn save(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unsave(conn: &PgConnection, form: &T) -> Result<usize, Error>
|
fn unsave(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Readable<T> {
|
pub trait Readable<Form> {
|
||||||
fn mark_as_read(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn mark_as_read(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn mark_as_unread(conn: &PgConnection, form: &T) -> Result<usize, Error>
|
fn mark_as_unread(conn: &PgConnection, form: &Form) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Reportable<T> {
|
pub trait Reportable<Form> {
|
||||||
fn report(conn: &PgConnection, form: &T) -> Result<Self, Error>
|
fn report(conn: &PgConnection, form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn resolve(conn: &PgConnection, report_id: i32, resolver_id: i32) -> Result<usize, Error>
|
fn resolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn unresolve(conn: &PgConnection, report_id: i32, resolver_id: i32) -> Result<usize, Error>
|
fn unresolve(conn: &PgConnection, report_id: i32, resolver_id: PersonId) -> Result<usize, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait ApubObject<T> {
|
pub trait ApubObject<Form> {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
fn upsert(conn: &PgConnection, user_form: &T) -> Result<Self, Error>
|
fn upsert(conn: &PgConnection, user_form: &Form) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
}
|
}
|
||||||
|
@ -219,6 +225,20 @@ pub fn diesel_option_overwrite(opt: &Option<String>) -> Option<Option<String>> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn diesel_option_overwrite_to_url(
|
||||||
|
opt: &Option<String>,
|
||||||
|
) -> Result<Option<Option<DbUrl>>, ApiError> {
|
||||||
|
match opt.as_ref().map(|s| s.as_str()) {
|
||||||
|
// An empty string is an erase
|
||||||
|
Some("") => Ok(Some(None)),
|
||||||
|
Some(str_url) => match Url::parse(str_url) {
|
||||||
|
Ok(url) => Ok(Some(Some(url.into()))),
|
||||||
|
Err(_) => Err(ApiError::err("invalid_url")),
|
||||||
|
},
|
||||||
|
None => Ok(None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
embed_migrations!();
|
embed_migrations!();
|
||||||
|
|
||||||
pub fn establish_unpooled_connection() -> PgConnection {
|
pub fn establish_unpooled_connection() -> PgConnection {
|
||||||
|
@ -231,13 +251,14 @@ pub fn establish_unpooled_connection() -> PgConnection {
|
||||||
};
|
};
|
||||||
let conn =
|
let conn =
|
||||||
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
|
PgConnection::establish(&db_url).unwrap_or_else(|_| panic!("Error connecting to {}", db_url));
|
||||||
embedded_migrations::run(&conn).unwrap();
|
embedded_migrations::run(&conn).expect("load migrations");
|
||||||
conn
|
conn
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref EMAIL_REGEX: Regex =
|
static ref EMAIL_REGEX: Regex =
|
||||||
Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$").unwrap();
|
Regex::new(r"^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$")
|
||||||
|
.expect("compile email regex");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub mod functions {
|
pub mod functions {
|
||||||
|
@ -250,7 +271,7 @@ pub mod functions {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::fuzzy_search;
|
use super::{fuzzy_search, *};
|
||||||
use crate::is_email_regex;
|
use crate::is_email_regex;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -264,4 +285,32 @@ mod tests {
|
||||||
assert!(is_email_regex("gush@gmail.com"));
|
assert!(is_email_regex("gush@gmail.com"));
|
||||||
assert!(!is_email_regex("nada_neutho"));
|
assert!(!is_email_regex("nada_neutho"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_diesel_option_overwrite() {
|
||||||
|
assert_eq!(diesel_option_overwrite(&None), None);
|
||||||
|
assert_eq!(diesel_option_overwrite(&Some("".to_string())), Some(None));
|
||||||
|
assert_eq!(
|
||||||
|
diesel_option_overwrite(&Some("test".to_string())),
|
||||||
|
Some(Some("test".to_string()))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_diesel_option_overwrite_to_url() {
|
||||||
|
assert!(matches!(diesel_option_overwrite_to_url(&None), Ok(None)));
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some("".to_string())),
|
||||||
|
Ok(Some(None))
|
||||||
|
));
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some("invalid_url".to_string())),
|
||||||
|
Err(_)
|
||||||
|
));
|
||||||
|
let example_url = "https://example.com";
|
||||||
|
assert!(matches!(
|
||||||
|
diesel_option_overwrite_to_url(&Some(example_url.to_string())),
|
||||||
|
Ok(Some(Some(url))) if url == Url::parse(&example_url).unwrap().into()
|
||||||
|
));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Crud;
|
use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
use diesel::{dsl::*, result::Error, sql_types::Text, *};
|
||||||
use lemmy_db_schema::{source::activity::*, Url};
|
use lemmy_db_schema::{source::activity::*, DbUrl};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
@ -9,7 +9,7 @@ use std::{
|
||||||
io::{Error as IoError, ErrorKind},
|
io::{Error as IoError, ErrorKind},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Crud<ActivityForm> for Activity {
|
impl Crud<ActivityForm, i32> for Activity {
|
||||||
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, activity_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
activity.find(activity_id).first::<Self>(conn)
|
activity.find(activity_id).first::<Self>(conn)
|
||||||
|
@ -41,7 +41,7 @@ impl Crud<ActivityForm> for Activity {
|
||||||
pub trait Activity_ {
|
pub trait Activity_ {
|
||||||
fn insert<T>(
|
fn insert<T>(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
ap_id: String,
|
ap_id: DbUrl,
|
||||||
data: &T,
|
data: &T,
|
||||||
local: bool,
|
local: bool,
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
|
@ -49,20 +49,20 @@ pub trait Activity_ {
|
||||||
where
|
where
|
||||||
T: Serialize + Debug;
|
T: Serialize + Debug;
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Activity, Error>;
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error>;
|
||||||
fn delete_olds(conn: &PgConnection) -> Result<usize, Error>;
|
fn delete_olds(conn: &PgConnection) -> Result<usize, Error>;
|
||||||
|
|
||||||
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
/// Returns up to 20 activities of type `Announce/Create/Page` from the community
|
||||||
fn read_community_outbox(
|
fn read_community_outbox(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_actor_id: &Url,
|
community_actor_id: &DbUrl,
|
||||||
) -> Result<Vec<Value>, Error>;
|
) -> Result<Vec<Value>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Activity_ for Activity {
|
impl Activity_ for Activity {
|
||||||
fn insert<T>(
|
fn insert<T>(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
ap_id: String,
|
ap_id: DbUrl,
|
||||||
data: &T,
|
data: &T,
|
||||||
local: bool,
|
local: bool,
|
||||||
sensitive: bool,
|
sensitive: bool,
|
||||||
|
@ -88,7 +88,7 @@ impl Activity_ for Activity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &str) -> Result<Activity, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Activity, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
activity.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
@ -100,7 +100,7 @@ impl Activity_ for Activity {
|
||||||
|
|
||||||
fn read_community_outbox(
|
fn read_community_outbox(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_actor_id: &Url,
|
community_actor_id: &DbUrl,
|
||||||
) -> Result<Vec<Value>, Error> {
|
) -> Result<Vec<Value>, Error> {
|
||||||
use lemmy_db_schema::schema::activity::dsl::*;
|
use lemmy_db_schema::schema::activity::dsl::*;
|
||||||
let res: Vec<Value> = activity
|
let res: Vec<Value> = activity
|
||||||
|
@ -121,47 +121,33 @@ impl Activity_ for Activity {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use super::*;
|
||||||
establish_unpooled_connection,
|
use crate::{establish_unpooled_connection, source::activity::Activity_};
|
||||||
source::activity::Activity_,
|
|
||||||
Crud,
|
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
activity::{Activity, ActivityForm},
|
activity::{Activity, ActivityForm},
|
||||||
user::{UserForm, User_},
|
person::{Person, PersonForm},
|
||||||
};
|
};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[serial]
|
#[serial]
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let creator_form = UserForm {
|
let creator_form = PersonForm {
|
||||||
name: "activity_creator_pm".into(),
|
name: "activity_creator_pm".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -169,10 +155,13 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_creator = User_::create(&conn, &creator_form).unwrap();
|
let inserted_creator = Person::create(&conn, &creator_form).unwrap();
|
||||||
|
|
||||||
let ap_id =
|
let ap_id: DbUrl = Url::parse(
|
||||||
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c";
|
"https://enterprise.lemmy.ml/activities/delete/f1b5d57c-80f8-4e03-a615-688d552e946c",
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
.into();
|
||||||
let test_json: Value = serde_json::from_str(
|
let test_json: Value = serde_json::from_str(
|
||||||
r#"{
|
r#"{
|
||||||
"@context": "https://www.w3.org/ns/activitystreams",
|
"@context": "https://www.w3.org/ns/activitystreams",
|
||||||
|
@ -188,7 +177,7 @@ mod tests {
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let activity_form = ActivityForm {
|
let activity_form = ActivityForm {
|
||||||
ap_id: ap_id.to_string(),
|
ap_id: ap_id.clone(),
|
||||||
data: test_json.to_owned(),
|
data: test_json.to_owned(),
|
||||||
local: true,
|
local: true,
|
||||||
sensitive: false,
|
sensitive: false,
|
||||||
|
@ -198,7 +187,7 @@ mod tests {
|
||||||
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
let inserted_activity = Activity::create(&conn, &activity_form).unwrap();
|
||||||
|
|
||||||
let expected_activity = Activity {
|
let expected_activity = Activity {
|
||||||
ap_id: Some(ap_id.to_string()),
|
ap_id: Some(ap_id.clone()),
|
||||||
id: inserted_activity.id,
|
id: inserted_activity.id,
|
||||||
data: test_json,
|
data: test_json,
|
||||||
local: true,
|
local: true,
|
||||||
|
@ -208,8 +197,8 @@ mod tests {
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
let read_activity = Activity::read(&conn, inserted_activity.id).unwrap();
|
||||||
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, ap_id).unwrap();
|
let read_activity_by_apub_id = Activity::read_from_apub_id(&conn, &ap_id).unwrap();
|
||||||
User_::delete(&conn, inserted_creator.id).unwrap();
|
Person::delete(&conn, inserted_creator.id).unwrap();
|
||||||
Activity::delete(&conn, inserted_activity.id).unwrap();
|
Activity::delete(&conn, inserted_activity.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_activity, read_activity);
|
assert_eq!(expected_activity, read_activity);
|
||||||
|
|
|
@ -10,40 +10,54 @@ use lemmy_db_schema::{
|
||||||
CommentSaved,
|
CommentSaved,
|
||||||
CommentSavedForm,
|
CommentSavedForm,
|
||||||
},
|
},
|
||||||
Url,
|
CommentId,
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub trait Comment_ {
|
pub trait Comment_ {
|
||||||
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: Url) -> Result<Comment, Error>;
|
fn update_ap_id(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: CommentId,
|
||||||
|
apub_id: DbUrl,
|
||||||
|
) -> Result<Comment, Error>;
|
||||||
fn permadelete_for_creator(
|
fn permadelete_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
) -> Result<Vec<Comment>, Error>;
|
) -> Result<Vec<Comment>, Error>;
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<Comment, Error>;
|
) -> Result<Comment, Error>;
|
||||||
fn update_removed(
|
fn update_removed(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Comment, Error>;
|
) -> Result<Comment, Error>;
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Comment>, Error>;
|
) -> Result<Vec<Comment>, Error>;
|
||||||
fn update_read(conn: &PgConnection, comment_id: i32, new_read: bool) -> Result<Comment, Error>;
|
fn update_read(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: CommentId,
|
||||||
|
new_read: bool,
|
||||||
|
) -> Result<Comment, Error>;
|
||||||
fn update_content(
|
fn update_content(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_content: &str,
|
new_content: &str,
|
||||||
) -> Result<Comment, Error>;
|
) -> Result<Comment, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Comment_ for Comment {
|
impl Comment_ for Comment {
|
||||||
fn update_ap_id(conn: &PgConnection, comment_id: i32, apub_id: Url) -> Result<Self, Error> {
|
fn update_ap_id(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: CommentId,
|
||||||
|
apub_id: DbUrl,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
|
||||||
diesel::update(comment.find(comment_id))
|
diesel::update(comment.find(comment_id))
|
||||||
|
@ -51,7 +65,10 @@ impl Comment_ for Comment {
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Self>, Error> {
|
fn permadelete_for_creator(
|
||||||
|
conn: &PgConnection,
|
||||||
|
for_creator_id: PersonId,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
diesel::update(comment.filter(creator_id.eq(for_creator_id)))
|
diesel::update(comment.filter(creator_id.eq(for_creator_id)))
|
||||||
.set((
|
.set((
|
||||||
|
@ -64,7 +81,7 @@ impl Comment_ for Comment {
|
||||||
|
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
@ -75,7 +92,7 @@ impl Comment_ for Comment {
|
||||||
|
|
||||||
fn update_removed(
|
fn update_removed(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
@ -86,7 +103,7 @@ impl Comment_ for Comment {
|
||||||
|
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Self>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
@ -95,7 +112,11 @@ impl Comment_ for Comment {
|
||||||
.get_results::<Self>(conn)
|
.get_results::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_read(conn: &PgConnection, comment_id: i32, new_read: bool) -> Result<Self, Error> {
|
fn update_read(
|
||||||
|
conn: &PgConnection,
|
||||||
|
comment_id: CommentId,
|
||||||
|
new_read: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
diesel::update(comment.find(comment_id))
|
diesel::update(comment.find(comment_id))
|
||||||
.set(read.eq(new_read))
|
.set(read.eq(new_read))
|
||||||
|
@ -104,7 +125,7 @@ impl Comment_ for Comment {
|
||||||
|
|
||||||
fn update_content(
|
fn update_content(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
new_content: &str,
|
new_content: &str,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
@ -114,13 +135,13 @@ impl Comment_ for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<CommentForm> for Comment {
|
impl Crud<CommentForm, CommentId> for Comment {
|
||||||
fn read(conn: &PgConnection, comment_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, comment_id: CommentId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
comment.find(comment_id).first::<Self>(conn)
|
comment.find(comment_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(conn: &PgConnection, comment_id: i32) -> Result<usize, Error> {
|
fn delete(conn: &PgConnection, comment_id: CommentId) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
diesel::delete(comment.find(comment_id)).execute(conn)
|
diesel::delete(comment.find(comment_id)).execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -134,7 +155,7 @@ impl Crud<CommentForm> for Comment {
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
comment_id: i32,
|
comment_id: CommentId,
|
||||||
comment_form: &CommentForm,
|
comment_form: &CommentForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
|
@ -145,7 +166,7 @@ impl Crud<CommentForm> for Comment {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommentForm> for Comment {
|
impl ApubObject<CommentForm> for Comment {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment::dsl::*;
|
use lemmy_db_schema::schema::comment::dsl::*;
|
||||||
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
comment.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
@ -161,22 +182,26 @@ impl ApubObject<CommentForm> for Comment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Likeable<CommentLikeForm> for CommentLike {
|
impl Likeable<CommentLikeForm, CommentId> for CommentLike {
|
||||||
fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
fn like(conn: &PgConnection, comment_like_form: &CommentLikeForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::comment_like::dsl::*;
|
use lemmy_db_schema::schema::comment_like::dsl::*;
|
||||||
insert_into(comment_like)
|
insert_into(comment_like)
|
||||||
.values(comment_like_form)
|
.values(comment_like_form)
|
||||||
.on_conflict((comment_id, user_id))
|
.on_conflict((comment_id, person_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(comment_like_form)
|
.set(comment_like_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
fn remove(conn: &PgConnection, user_id: i32, comment_id: i32) -> Result<usize, Error> {
|
fn remove(
|
||||||
|
conn: &PgConnection,
|
||||||
|
person_id: PersonId,
|
||||||
|
comment_id: CommentId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::comment_like::dsl;
|
use lemmy_db_schema::schema::comment_like::dsl;
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
dsl::comment_like
|
dsl::comment_like
|
||||||
.filter(dsl::comment_id.eq(comment_id))
|
.filter(dsl::comment_id.eq(comment_id))
|
||||||
.filter(dsl::user_id.eq(user_id)),
|
.filter(dsl::person_id.eq(person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -187,7 +212,7 @@ impl Saveable<CommentSavedForm> for CommentSaved {
|
||||||
use lemmy_db_schema::schema::comment_saved::dsl::*;
|
use lemmy_db_schema::schema::comment_saved::dsl::*;
|
||||||
insert_into(comment_saved)
|
insert_into(comment_saved)
|
||||||
.values(comment_saved_form)
|
.values(comment_saved_form)
|
||||||
.on_conflict((comment_id, user_id))
|
.on_conflict((comment_id, person_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(comment_saved_form)
|
.set(comment_saved_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -197,7 +222,7 @@ impl Saveable<CommentSavedForm> for CommentSaved {
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
comment_saved
|
comment_saved
|
||||||
.filter(comment_id.eq(comment_saved_form.comment_id))
|
.filter(comment_id.eq(comment_saved_form.comment_id))
|
||||||
.filter(user_id.eq(comment_saved_form.user_id)),
|
.filter(person_id.eq(comment_saved_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -205,12 +230,12 @@ impl Saveable<CommentSavedForm> for CommentSaved {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{establish_unpooled_connection, Crud, Likeable, ListingType, Saveable, SortType};
|
use crate::{establish_unpooled_connection, Crud, Likeable, Saveable};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::*,
|
comment::*,
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::{Person, PersonForm},
|
||||||
post::*,
|
post::*,
|
||||||
user::{UserForm, User_},
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -219,28 +244,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "terry".into(),
|
name: "terry".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -248,13 +263,13 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "test community".to_string(),
|
name: "test community".to_string(),
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
@ -276,7 +291,7 @@ mod tests {
|
||||||
|
|
||||||
let new_post = PostForm {
|
let new_post = PostForm {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
|
@ -299,7 +314,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -316,7 +331,7 @@ mod tests {
|
||||||
let expected_comment = Comment {
|
let expected_comment = Comment {
|
||||||
id: inserted_comment.id,
|
id: inserted_comment.id,
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: false,
|
removed: false,
|
||||||
deleted: false,
|
deleted: false,
|
||||||
|
@ -330,7 +345,7 @@ mod tests {
|
||||||
|
|
||||||
let child_comment_form = CommentForm {
|
let child_comment_form = CommentForm {
|
||||||
content: "A child comment".into(),
|
content: "A child comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
parent_id: Some(inserted_comment.id),
|
parent_id: Some(inserted_comment.id),
|
||||||
removed: None,
|
removed: None,
|
||||||
|
@ -348,7 +363,7 @@ mod tests {
|
||||||
let comment_like_form = CommentLikeForm {
|
let comment_like_form = CommentLikeForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -358,7 +373,7 @@ mod tests {
|
||||||
id: inserted_comment_like.id,
|
id: inserted_comment_like.id,
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_comment_like.published,
|
published: inserted_comment_like.published,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
@ -366,7 +381,7 @@ mod tests {
|
||||||
// Comment Saved
|
// Comment Saved
|
||||||
let comment_saved_form = CommentSavedForm {
|
let comment_saved_form = CommentSavedForm {
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
|
let inserted_comment_saved = CommentSaved::save(&conn, &comment_saved_form).unwrap();
|
||||||
|
@ -374,19 +389,19 @@ mod tests {
|
||||||
let expected_comment_saved = CommentSaved {
|
let expected_comment_saved = CommentSaved {
|
||||||
id: inserted_comment_saved.id,
|
id: inserted_comment_saved.id,
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_comment_saved.published,
|
published: inserted_comment_saved.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
|
let read_comment = Comment::read(&conn, inserted_comment.id).unwrap();
|
||||||
let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
|
let updated_comment = Comment::update(&conn, inserted_comment.id, &comment_form).unwrap();
|
||||||
let like_removed = CommentLike::remove(&conn, inserted_user.id, inserted_comment.id).unwrap();
|
let like_removed = CommentLike::remove(&conn, inserted_person.id, inserted_comment.id).unwrap();
|
||||||
let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
|
let saved_removed = CommentSaved::unsave(&conn, &comment_saved_form).unwrap();
|
||||||
let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
|
let num_deleted = Comment::delete(&conn, inserted_comment.id).unwrap();
|
||||||
Comment::delete(&conn, inserted_child_comment.id).unwrap();
|
Comment::delete(&conn, inserted_child_comment.id).unwrap();
|
||||||
Post::delete(&conn, inserted_post.id).unwrap();
|
Post::delete(&conn, inserted_post.id).unwrap();
|
||||||
Community::delete(&conn, inserted_community.id).unwrap();
|
Community::delete(&conn, inserted_community.id).unwrap();
|
||||||
User_::delete(&conn, inserted_user.id).unwrap();
|
Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_comment, read_comment);
|
assert_eq!(expected_comment, read_comment);
|
||||||
assert_eq!(expected_comment, inserted_comment);
|
assert_eq!(expected_comment, inserted_comment);
|
||||||
|
|
|
@ -3,6 +3,7 @@ use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{
|
use lemmy_db_schema::{
|
||||||
naive_now,
|
naive_now,
|
||||||
source::comment_report::{CommentReport, CommentReportForm},
|
source::comment_report::{CommentReport, CommentReportForm},
|
||||||
|
PersonId,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Reportable<CommentReportForm> for CommentReport {
|
impl Reportable<CommentReportForm> for CommentReport {
|
||||||
|
@ -22,7 +23,11 @@ impl Reportable<CommentReportForm> for CommentReport {
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
/// * `report_id` - the id of the report to resolve
|
/// * `report_id` - the id of the report to resolve
|
||||||
/// * `by_resolver_id` - the id of the user resolving the report
|
/// * `by_resolver_id` - the id of the user resolving the report
|
||||||
fn resolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result<usize, Error> {
|
fn resolve(
|
||||||
|
conn: &PgConnection,
|
||||||
|
report_id: i32,
|
||||||
|
by_resolver_id: PersonId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::comment_report::dsl::*;
|
use lemmy_db_schema::schema::comment_report::dsl::*;
|
||||||
update(comment_report.find(report_id))
|
update(comment_report.find(report_id))
|
||||||
.set((
|
.set((
|
||||||
|
@ -38,7 +43,11 @@ impl Reportable<CommentReportForm> for CommentReport {
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
/// * `report_id` - the id of the report to unresolve
|
/// * `report_id` - the id of the report to unresolve
|
||||||
/// * `by_resolver_id` - the id of the user unresolving the report
|
/// * `by_resolver_id` - the id of the user unresolving the report
|
||||||
fn unresolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result<usize, Error> {
|
fn unresolve(
|
||||||
|
conn: &PgConnection,
|
||||||
|
report_id: i32,
|
||||||
|
by_resolver_id: PersonId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::comment_report::dsl::*;
|
use lemmy_db_schema::schema::comment_report::dsl::*;
|
||||||
update(comment_report.find(report_id))
|
update(comment_report.find(report_id))
|
||||||
.set((
|
.set((
|
||||||
|
|
|
@ -9,10 +9,12 @@ use lemmy_db_schema::{
|
||||||
CommunityForm,
|
CommunityForm,
|
||||||
CommunityModerator,
|
CommunityModerator,
|
||||||
CommunityModeratorForm,
|
CommunityModeratorForm,
|
||||||
CommunityUserBan,
|
CommunityPersonBan,
|
||||||
CommunityUserBanForm,
|
CommunityPersonBanForm,
|
||||||
},
|
},
|
||||||
Url,
|
CommunityId,
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
};
|
};
|
||||||
|
|
||||||
mod safe_type {
|
mod safe_type {
|
||||||
|
@ -59,13 +61,13 @@ mod safe_type {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<CommunityForm> for Community {
|
impl Crud<CommunityForm, CommunityId> for Community {
|
||||||
fn read(conn: &PgConnection, community_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, community_id: CommunityId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community.find(community_id).first::<Self>(conn)
|
community.find(community_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(conn: &PgConnection, community_id: i32) -> Result<usize, Error> {
|
fn delete(conn: &PgConnection, community_id: CommunityId) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
diesel::delete(community.find(community_id)).execute(conn)
|
diesel::delete(community.find(community_id)).execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -79,7 +81,7 @@ impl Crud<CommunityForm> for Community {
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_community: &CommunityForm,
|
new_community: &CommunityForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
|
@ -90,7 +92,7 @@ impl Crud<CommunityForm> for Community {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<CommunityForm> for Community {
|
impl ApubObject<CommunityForm> for Community {
|
||||||
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, for_actor_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community
|
community
|
||||||
.filter(actor_id.eq(for_actor_id))
|
.filter(actor_id.eq(for_actor_id))
|
||||||
|
@ -112,26 +114,29 @@ pub trait Community_ {
|
||||||
fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error>;
|
fn read_from_name(conn: &PgConnection, community_name: &str) -> Result<Community, Error>;
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<Community, Error>;
|
) -> Result<Community, Error>;
|
||||||
fn update_removed(
|
fn update_removed(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Community, Error>;
|
) -> Result<Community, Error>;
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Community>, Error>;
|
) -> Result<Vec<Community>, Error>;
|
||||||
fn update_creator(
|
fn update_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_creator_id: i32,
|
new_creator_id: PersonId,
|
||||||
) -> Result<Community, Error>;
|
) -> Result<Community, Error>;
|
||||||
fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error>;
|
fn distinct_federated_communities(conn: &PgConnection) -> Result<Vec<String>, Error>;
|
||||||
fn read_from_followers_url(conn: &PgConnection, followers_url: &Url) -> Result<Community, Error>;
|
fn read_from_followers_url(
|
||||||
|
conn: &PgConnection,
|
||||||
|
followers_url: &DbUrl,
|
||||||
|
) -> Result<Community, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Community_ for Community {
|
impl Community_ for Community {
|
||||||
|
@ -145,7 +150,7 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<Community, Error> {
|
) -> Result<Community, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
|
@ -156,7 +161,7 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn update_removed(
|
fn update_removed(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Community, Error> {
|
) -> Result<Community, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
|
@ -167,7 +172,7 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Community>, Error> {
|
) -> Result<Vec<Community>, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
|
@ -178,8 +183,8 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn update_creator(
|
fn update_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_id: i32,
|
community_id: CommunityId,
|
||||||
new_creator_id: i32,
|
new_creator_id: PersonId,
|
||||||
) -> Result<Community, Error> {
|
) -> Result<Community, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
diesel::update(community.find(community_id))
|
diesel::update(community.find(community_id))
|
||||||
|
@ -194,7 +199,7 @@ impl Community_ for Community {
|
||||||
|
|
||||||
fn read_from_followers_url(
|
fn read_from_followers_url(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
followers_url_: &Url,
|
followers_url_: &DbUrl,
|
||||||
) -> Result<Community, Error> {
|
) -> Result<Community, Error> {
|
||||||
use lemmy_db_schema::schema::community::dsl::*;
|
use lemmy_db_schema::schema::community::dsl::*;
|
||||||
community
|
community
|
||||||
|
@ -206,74 +211,80 @@ impl Community_ for Community {
|
||||||
impl Joinable<CommunityModeratorForm> for CommunityModerator {
|
impl Joinable<CommunityModeratorForm> for CommunityModerator {
|
||||||
fn join(
|
fn join(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_user_form: &CommunityModeratorForm,
|
community_moderator_form: &CommunityModeratorForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
||||||
insert_into(community_moderator)
|
insert_into(community_moderator)
|
||||||
.values(community_user_form)
|
.values(community_moderator_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn leave(
|
fn leave(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_user_form: &CommunityModeratorForm,
|
community_moderator_form: &CommunityModeratorForm,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
community_moderator
|
community_moderator
|
||||||
.filter(community_id.eq(community_user_form.community_id))
|
.filter(community_id.eq(community_moderator_form.community_id))
|
||||||
.filter(user_id.eq(community_user_form.user_id)),
|
.filter(person_id.eq(community_moderator_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait CommunityModerator_ {
|
pub trait CommunityModerator_ {
|
||||||
fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error>;
|
fn delete_for_community(
|
||||||
fn get_user_moderated_communities(
|
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_user_id: i32,
|
for_community_id: CommunityId,
|
||||||
) -> Result<Vec<i32>, Error>;
|
) -> Result<usize, Error>;
|
||||||
|
fn get_person_moderated_communities(
|
||||||
|
conn: &PgConnection,
|
||||||
|
for_person_id: PersonId,
|
||||||
|
) -> Result<Vec<CommunityId>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CommunityModerator_ for CommunityModerator {
|
impl CommunityModerator_ for CommunityModerator {
|
||||||
fn delete_for_community(conn: &PgConnection, for_community_id: i32) -> Result<usize, Error> {
|
fn delete_for_community(
|
||||||
|
conn: &PgConnection,
|
||||||
|
for_community_id: CommunityId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
||||||
diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
|
diesel::delete(community_moderator.filter(community_id.eq(for_community_id))).execute(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_user_moderated_communities(
|
fn get_person_moderated_communities(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_user_id: i32,
|
for_person_id: PersonId,
|
||||||
) -> Result<Vec<i32>, Error> {
|
) -> Result<Vec<CommunityId>, Error> {
|
||||||
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
use lemmy_db_schema::schema::community_moderator::dsl::*;
|
||||||
community_moderator
|
community_moderator
|
||||||
.filter(user_id.eq(for_user_id))
|
.filter(person_id.eq(for_person_id))
|
||||||
.select(community_id)
|
.select(community_id)
|
||||||
.load::<i32>(conn)
|
.load::<CommunityId>(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Bannable<CommunityUserBanForm> for CommunityUserBan {
|
impl Bannable<CommunityPersonBanForm> for CommunityPersonBan {
|
||||||
fn ban(
|
fn ban(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_user_ban_form: &CommunityUserBanForm,
|
community_person_ban_form: &CommunityPersonBanForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::community_user_ban::dsl::*;
|
use lemmy_db_schema::schema::community_person_ban::dsl::*;
|
||||||
insert_into(community_user_ban)
|
insert_into(community_person_ban)
|
||||||
.values(community_user_ban_form)
|
.values(community_person_ban_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unban(
|
fn unban(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
community_user_ban_form: &CommunityUserBanForm,
|
community_person_ban_form: &CommunityPersonBanForm,
|
||||||
) -> Result<usize, Error> {
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::community_user_ban::dsl::*;
|
use lemmy_db_schema::schema::community_person_ban::dsl::*;
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
community_user_ban
|
community_person_ban
|
||||||
.filter(community_id.eq(community_user_ban_form.community_id))
|
.filter(community_id.eq(community_person_ban_form.community_id))
|
||||||
.filter(user_id.eq(community_user_ban_form.user_id)),
|
.filter(person_id.eq(community_person_ban_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -287,12 +298,16 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
|
||||||
use lemmy_db_schema::schema::community_follower::dsl::*;
|
use lemmy_db_schema::schema::community_follower::dsl::*;
|
||||||
insert_into(community_follower)
|
insert_into(community_follower)
|
||||||
.values(community_follower_form)
|
.values(community_follower_form)
|
||||||
.on_conflict((community_id, user_id))
|
.on_conflict((community_id, person_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(community_follower_form)
|
.set(community_follower_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
fn follow_accepted(conn: &PgConnection, community_id_: i32, user_id_: i32) -> Result<Self, Error>
|
fn follow_accepted(
|
||||||
|
conn: &PgConnection,
|
||||||
|
community_id_: CommunityId,
|
||||||
|
person_id_: PersonId,
|
||||||
|
) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -300,7 +315,7 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
|
||||||
diesel::update(
|
diesel::update(
|
||||||
community_follower
|
community_follower
|
||||||
.filter(community_id.eq(community_id_))
|
.filter(community_id.eq(community_id_))
|
||||||
.filter(user_id.eq(user_id_)),
|
.filter(person_id.eq(person_id_)),
|
||||||
)
|
)
|
||||||
.set(pending.eq(true))
|
.set(pending.eq(true))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -313,13 +328,13 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
community_follower
|
community_follower
|
||||||
.filter(community_id.eq(&community_follower_form.community_id))
|
.filter(community_id.eq(&community_follower_form.community_id))
|
||||||
.filter(user_id.eq(&community_follower_form.user_id)),
|
.filter(person_id.eq(&community_follower_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
// TODO: this function name only makes sense if you call it with a remote community. for a local
|
// TODO: this function name only makes sense if you call it with a remote community. for a local
|
||||||
// community, it will also return true if only remote followers exist
|
// community, it will also return true if only remote followers exist
|
||||||
fn has_local_followers(conn: &PgConnection, community_id_: i32) -> Result<bool, Error> {
|
fn has_local_followers(conn: &PgConnection, community_id_: CommunityId) -> Result<bool, Error> {
|
||||||
use lemmy_db_schema::schema::community_follower::dsl::*;
|
use lemmy_db_schema::schema::community_follower::dsl::*;
|
||||||
diesel::select(exists(
|
diesel::select(exists(
|
||||||
community_follower.filter(community_id.eq(community_id_)),
|
community_follower.filter(community_id.eq(community_id_)),
|
||||||
|
@ -330,16 +345,8 @@ impl Followable<CommunityFollowerForm> for CommunityFollower {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{establish_unpooled_connection, Bannable, Crud, Followable, Joinable};
|
||||||
establish_unpooled_connection,
|
use lemmy_db_schema::source::{community::*, person::*};
|
||||||
Bannable,
|
|
||||||
Crud,
|
|
||||||
Followable,
|
|
||||||
Joinable,
|
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{community::*, user::*};
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -347,28 +354,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "bobbee".into(),
|
name: "bobbee".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -376,11 +373,11 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "TIL".into(),
|
name: "TIL".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
nsfw: false,
|
nsfw: false,
|
||||||
|
@ -404,7 +401,7 @@ mod tests {
|
||||||
|
|
||||||
let expected_community = Community {
|
let expected_community = Community {
|
||||||
id: inserted_community.id,
|
id: inserted_community.id,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
name: "TIL".into(),
|
name: "TIL".into(),
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
|
@ -427,7 +424,7 @@ mod tests {
|
||||||
|
|
||||||
let community_follower_form = CommunityFollowerForm {
|
let community_follower_form = CommunityFollowerForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
pending: false,
|
pending: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -437,55 +434,56 @@ mod tests {
|
||||||
let expected_community_follower = CommunityFollower {
|
let expected_community_follower = CommunityFollower {
|
||||||
id: inserted_community_follower.id,
|
id: inserted_community_follower.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
pending: Some(false),
|
pending: Some(false),
|
||||||
published: inserted_community_follower.published,
|
published: inserted_community_follower.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_user_form = CommunityModeratorForm {
|
let community_moderator_form = CommunityModeratorForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_community_user = CommunityModerator::join(&conn, &community_user_form).unwrap();
|
let inserted_community_moderator =
|
||||||
|
CommunityModerator::join(&conn, &community_moderator_form).unwrap();
|
||||||
|
|
||||||
let expected_community_user = CommunityModerator {
|
let expected_community_moderator = CommunityModerator {
|
||||||
id: inserted_community_user.id,
|
id: inserted_community_moderator.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_community_user.published,
|
published: inserted_community_moderator.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let community_user_ban_form = CommunityUserBanForm {
|
let community_person_ban_form = CommunityPersonBanForm {
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_community_user_ban =
|
let inserted_community_person_ban =
|
||||||
CommunityUserBan::ban(&conn, &community_user_ban_form).unwrap();
|
CommunityPersonBan::ban(&conn, &community_person_ban_form).unwrap();
|
||||||
|
|
||||||
let expected_community_user_ban = CommunityUserBan {
|
let expected_community_person_ban = CommunityPersonBan {
|
||||||
id: inserted_community_user_ban.id,
|
id: inserted_community_person_ban.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_community_user_ban.published,
|
published: inserted_community_person_ban.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_community = Community::read(&conn, inserted_community.id).unwrap();
|
let read_community = Community::read(&conn, inserted_community.id).unwrap();
|
||||||
let updated_community =
|
let updated_community =
|
||||||
Community::update(&conn, inserted_community.id, &new_community).unwrap();
|
Community::update(&conn, inserted_community.id, &new_community).unwrap();
|
||||||
let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap();
|
let ignored_community = CommunityFollower::unfollow(&conn, &community_follower_form).unwrap();
|
||||||
let left_community = CommunityModerator::leave(&conn, &community_user_form).unwrap();
|
let left_community = CommunityModerator::leave(&conn, &community_moderator_form).unwrap();
|
||||||
let unban = CommunityUserBan::unban(&conn, &community_user_ban_form).unwrap();
|
let unban = CommunityPersonBan::unban(&conn, &community_person_ban_form).unwrap();
|
||||||
let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
|
let num_deleted = Community::delete(&conn, inserted_community.id).unwrap();
|
||||||
User_::delete(&conn, inserted_user.id).unwrap();
|
Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_community, read_community);
|
assert_eq!(expected_community, read_community);
|
||||||
assert_eq!(expected_community, inserted_community);
|
assert_eq!(expected_community, inserted_community);
|
||||||
assert_eq!(expected_community, updated_community);
|
assert_eq!(expected_community, updated_community);
|
||||||
assert_eq!(expected_community_follower, inserted_community_follower);
|
assert_eq!(expected_community_follower, inserted_community_follower);
|
||||||
assert_eq!(expected_community_user, inserted_community_user);
|
assert_eq!(expected_community_moderator, inserted_community_moderator);
|
||||||
assert_eq!(expected_community_user_ban, inserted_community_user_ban);
|
assert_eq!(expected_community_person_ban, inserted_community_person_ban);
|
||||||
assert_eq!(1, ignored_community);
|
assert_eq!(1, ignored_community);
|
||||||
assert_eq!(1, left_community);
|
assert_eq!(1, left_community);
|
||||||
assert_eq!(1, unban);
|
assert_eq!(1, unban);
|
||||||
|
|
119
crates/db_queries/src/source/local_user.rs
Normal file
119
crates/db_queries/src/source/local_user.rs
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
use crate::Crud;
|
||||||
|
use bcrypt::{hash, DEFAULT_COST};
|
||||||
|
use diesel::{dsl::*, result::Error, *};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
naive_now,
|
||||||
|
schema::local_user::dsl::*,
|
||||||
|
source::local_user::{LocalUser, LocalUserForm},
|
||||||
|
LocalUserId,
|
||||||
|
PersonId,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod safe_settings_type {
|
||||||
|
use crate::ToSafeSettings;
|
||||||
|
use lemmy_db_schema::{schema::local_user::columns::*, source::local_user::LocalUser};
|
||||||
|
|
||||||
|
type Columns = (
|
||||||
|
id,
|
||||||
|
person_id,
|
||||||
|
email,
|
||||||
|
admin,
|
||||||
|
show_nsfw,
|
||||||
|
theme,
|
||||||
|
default_sort_type,
|
||||||
|
default_listing_type,
|
||||||
|
lang,
|
||||||
|
show_avatars,
|
||||||
|
send_notifications_to_email,
|
||||||
|
matrix_user_id,
|
||||||
|
validator_time,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl ToSafeSettings for LocalUser {
|
||||||
|
type SafeSettingsColumns = Columns;
|
||||||
|
|
||||||
|
/// Includes everything but the hashed password
|
||||||
|
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
person_id,
|
||||||
|
email,
|
||||||
|
admin,
|
||||||
|
show_nsfw,
|
||||||
|
theme,
|
||||||
|
default_sort_type,
|
||||||
|
default_listing_type,
|
||||||
|
lang,
|
||||||
|
show_avatars,
|
||||||
|
send_notifications_to_email,
|
||||||
|
matrix_user_id,
|
||||||
|
validator_time,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait LocalUser_ {
|
||||||
|
fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<LocalUser, Error>;
|
||||||
|
fn update_password(
|
||||||
|
conn: &PgConnection,
|
||||||
|
local_user_id: LocalUserId,
|
||||||
|
new_password: &str,
|
||||||
|
) -> Result<LocalUser, Error>;
|
||||||
|
fn add_admin(conn: &PgConnection, person_id: PersonId, added: bool) -> Result<LocalUser, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LocalUser_ for LocalUser {
|
||||||
|
fn register(conn: &PgConnection, form: &LocalUserForm) -> Result<Self, Error> {
|
||||||
|
let mut edited_user = form.clone();
|
||||||
|
let password_hash =
|
||||||
|
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
|
||||||
|
edited_user.password_encrypted = password_hash;
|
||||||
|
|
||||||
|
Self::create(&conn, &edited_user)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn update_password(
|
||||||
|
conn: &PgConnection,
|
||||||
|
local_user_id: LocalUserId,
|
||||||
|
new_password: &str,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
|
||||||
|
|
||||||
|
diesel::update(local_user.find(local_user_id))
|
||||||
|
.set((
|
||||||
|
password_encrypted.eq(password_hash),
|
||||||
|
validator_time.eq(naive_now()),
|
||||||
|
))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn add_admin(conn: &PgConnection, for_person_id: PersonId, added: bool) -> Result<Self, Error> {
|
||||||
|
diesel::update(local_user.filter(person_id.eq(for_person_id)))
|
||||||
|
.set(admin.eq(added))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Crud<LocalUserForm, LocalUserId> for LocalUser {
|
||||||
|
fn read(conn: &PgConnection, local_user_id: LocalUserId) -> Result<Self, Error> {
|
||||||
|
local_user.find(local_user_id).first::<Self>(conn)
|
||||||
|
}
|
||||||
|
fn delete(conn: &PgConnection, local_user_id: LocalUserId) -> Result<usize, Error> {
|
||||||
|
diesel::delete(local_user.find(local_user_id)).execute(conn)
|
||||||
|
}
|
||||||
|
fn create(conn: &PgConnection, form: &LocalUserForm) -> Result<Self, Error> {
|
||||||
|
insert_into(local_user)
|
||||||
|
.values(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
fn update(
|
||||||
|
conn: &PgConnection,
|
||||||
|
local_user_id: LocalUserId,
|
||||||
|
form: &LocalUserForm,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
|
diesel::update(local_user.find(local_user_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,11 +2,12 @@ pub mod activity;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod comment_report;
|
pub mod comment_report;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod local_user;
|
||||||
pub mod moderator;
|
pub mod moderator;
|
||||||
pub mod password_reset_request;
|
pub mod password_reset_request;
|
||||||
|
pub mod person;
|
||||||
|
pub mod person_mention;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod post_report;
|
pub mod post_report;
|
||||||
pub mod private_message;
|
pub mod private_message;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod user;
|
|
||||||
pub mod user_mention;
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::source::moderator::*;
|
use lemmy_db_schema::source::moderator::*;
|
||||||
|
|
||||||
impl Crud<ModRemovePostForm> for ModRemovePost {
|
impl Crud<ModRemovePostForm, i32> for ModRemovePost {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_post::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_post::dsl::*;
|
||||||
mod_remove_post.find(from_id).first::<Self>(conn)
|
mod_remove_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -23,7 +23,7 @@ impl Crud<ModRemovePostForm> for ModRemovePost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModLockPostForm> for ModLockPost {
|
impl Crud<ModLockPostForm, i32> for ModLockPost {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_lock_post::dsl::*;
|
use lemmy_db_schema::schema::mod_lock_post::dsl::*;
|
||||||
mod_lock_post.find(from_id).first::<Self>(conn)
|
mod_lock_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -44,7 +44,7 @@ impl Crud<ModLockPostForm> for ModLockPost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModStickyPostForm> for ModStickyPost {
|
impl Crud<ModStickyPostForm, i32> for ModStickyPost {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_sticky_post::dsl::*;
|
use lemmy_db_schema::schema::mod_sticky_post::dsl::*;
|
||||||
mod_sticky_post.find(from_id).first::<Self>(conn)
|
mod_sticky_post.find(from_id).first::<Self>(conn)
|
||||||
|
@ -65,7 +65,7 @@ impl Crud<ModStickyPostForm> for ModStickyPost {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModRemoveCommentForm> for ModRemoveComment {
|
impl Crud<ModRemoveCommentForm, i32> for ModRemoveComment {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_comment::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_comment::dsl::*;
|
||||||
mod_remove_comment.find(from_id).first::<Self>(conn)
|
mod_remove_comment.find(from_id).first::<Self>(conn)
|
||||||
|
@ -86,7 +86,7 @@ impl Crud<ModRemoveCommentForm> for ModRemoveComment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModRemoveCommunityForm> for ModRemoveCommunity {
|
impl Crud<ModRemoveCommunityForm, i32> for ModRemoveCommunity {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_remove_community::dsl::*;
|
use lemmy_db_schema::schema::mod_remove_community::dsl::*;
|
||||||
mod_remove_community.find(from_id).first::<Self>(conn)
|
mod_remove_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -111,7 +111,7 @@ impl Crud<ModRemoveCommunityForm> for ModRemoveCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModBanFromCommunityForm> for ModBanFromCommunity {
|
impl Crud<ModBanFromCommunityForm, i32> for ModBanFromCommunity {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_ban_from_community::dsl::*;
|
use lemmy_db_schema::schema::mod_ban_from_community::dsl::*;
|
||||||
mod_ban_from_community.find(from_id).first::<Self>(conn)
|
mod_ban_from_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -136,7 +136,7 @@ impl Crud<ModBanFromCommunityForm> for ModBanFromCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModBanForm> for ModBan {
|
impl Crud<ModBanForm, i32> for ModBan {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_ban::dsl::*;
|
use lemmy_db_schema::schema::mod_ban::dsl::*;
|
||||||
mod_ban.find(from_id).first::<Self>(conn)
|
mod_ban.find(from_id).first::<Self>(conn)
|
||||||
|
@ -155,7 +155,7 @@ impl Crud<ModBanForm> for ModBan {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModAddCommunityForm> for ModAddCommunity {
|
impl Crud<ModAddCommunityForm, i32> for ModAddCommunity {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_add_community::dsl::*;
|
use lemmy_db_schema::schema::mod_add_community::dsl::*;
|
||||||
mod_add_community.find(from_id).first::<Self>(conn)
|
mod_add_community.find(from_id).first::<Self>(conn)
|
||||||
|
@ -176,7 +176,7 @@ impl Crud<ModAddCommunityForm> for ModAddCommunity {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Crud<ModAddForm> for ModAdd {
|
impl Crud<ModAddForm, i32> for ModAdd {
|
||||||
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, from_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::mod_add::dsl::*;
|
use lemmy_db_schema::schema::mod_add::dsl::*;
|
||||||
mod_add.find(from_id).first::<Self>(conn)
|
mod_add.find(from_id).first::<Self>(conn)
|
||||||
|
@ -197,8 +197,8 @@ impl Crud<ModAddForm> for ModAdd {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{establish_unpooled_connection, Crud, ListingType, SortType};
|
use crate::{establish_unpooled_connection, Crud};
|
||||||
use lemmy_db_schema::source::{comment::*, community::*, moderator::*, post::*, user::*};
|
use lemmy_db_schema::source::{comment::*, community::*, moderator::*, person::*, post::*};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
// use Crud;
|
// use Crud;
|
||||||
|
@ -207,28 +207,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_mod = UserForm {
|
let new_mod = PersonForm {
|
||||||
name: "the mod".into(),
|
name: "the mod".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -236,30 +226,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_mod = User_::create(&conn, &new_mod).unwrap();
|
let inserted_mod = Person::create(&conn, &new_mod).unwrap();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "jim2".into(),
|
name: "jim2".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -267,13 +247,13 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "mod_community".to_string(),
|
name: "mod_community".to_string(),
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
@ -297,7 +277,7 @@ mod tests {
|
||||||
name: "A test post thweep".into(),
|
name: "A test post thweep".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -318,7 +298,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -336,7 +316,7 @@ mod tests {
|
||||||
|
|
||||||
// remove post
|
// remove post
|
||||||
let mod_remove_post_form = ModRemovePostForm {
|
let mod_remove_post_form = ModRemovePostForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: None,
|
removed: None,
|
||||||
|
@ -346,7 +326,7 @@ mod tests {
|
||||||
let expected_mod_remove_post = ModRemovePost {
|
let expected_mod_remove_post = ModRemovePost {
|
||||||
id: inserted_mod_remove_post.id,
|
id: inserted_mod_remove_post.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: Some(true),
|
removed: Some(true),
|
||||||
when_: inserted_mod_remove_post.when_,
|
when_: inserted_mod_remove_post.when_,
|
||||||
|
@ -355,7 +335,7 @@ mod tests {
|
||||||
// lock post
|
// lock post
|
||||||
|
|
||||||
let mod_lock_post_form = ModLockPostForm {
|
let mod_lock_post_form = ModLockPostForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
locked: None,
|
locked: None,
|
||||||
};
|
};
|
||||||
|
@ -364,7 +344,7 @@ mod tests {
|
||||||
let expected_mod_lock_post = ModLockPost {
|
let expected_mod_lock_post = ModLockPost {
|
||||||
id: inserted_mod_lock_post.id,
|
id: inserted_mod_lock_post.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
locked: Some(true),
|
locked: Some(true),
|
||||||
when_: inserted_mod_lock_post.when_,
|
when_: inserted_mod_lock_post.when_,
|
||||||
};
|
};
|
||||||
|
@ -372,7 +352,7 @@ mod tests {
|
||||||
// sticky post
|
// sticky post
|
||||||
|
|
||||||
let mod_sticky_post_form = ModStickyPostForm {
|
let mod_sticky_post_form = ModStickyPostForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
stickied: None,
|
stickied: None,
|
||||||
};
|
};
|
||||||
|
@ -381,7 +361,7 @@ mod tests {
|
||||||
let expected_mod_sticky_post = ModStickyPost {
|
let expected_mod_sticky_post = ModStickyPost {
|
||||||
id: inserted_mod_sticky_post.id,
|
id: inserted_mod_sticky_post.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
stickied: Some(true),
|
stickied: Some(true),
|
||||||
when_: inserted_mod_sticky_post.when_,
|
when_: inserted_mod_sticky_post.when_,
|
||||||
};
|
};
|
||||||
|
@ -389,7 +369,7 @@ mod tests {
|
||||||
// comment
|
// comment
|
||||||
|
|
||||||
let mod_remove_comment_form = ModRemoveCommentForm {
|
let mod_remove_comment_form = ModRemoveCommentForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: None,
|
removed: None,
|
||||||
|
@ -401,7 +381,7 @@ mod tests {
|
||||||
let expected_mod_remove_comment = ModRemoveComment {
|
let expected_mod_remove_comment = ModRemoveComment {
|
||||||
id: inserted_mod_remove_comment.id,
|
id: inserted_mod_remove_comment.id,
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: Some(true),
|
removed: Some(true),
|
||||||
when_: inserted_mod_remove_comment.when_,
|
when_: inserted_mod_remove_comment.when_,
|
||||||
|
@ -410,7 +390,7 @@ mod tests {
|
||||||
// community
|
// community
|
||||||
|
|
||||||
let mod_remove_community_form = ModRemoveCommunityForm {
|
let mod_remove_community_form = ModRemoveCommunityForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: None,
|
removed: None,
|
||||||
|
@ -423,7 +403,7 @@ mod tests {
|
||||||
let expected_mod_remove_community = ModRemoveCommunity {
|
let expected_mod_remove_community = ModRemoveCommunity {
|
||||||
id: inserted_mod_remove_community.id,
|
id: inserted_mod_remove_community.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
removed: Some(true),
|
removed: Some(true),
|
||||||
expires: None,
|
expires: None,
|
||||||
|
@ -433,8 +413,8 @@ mod tests {
|
||||||
// ban from community
|
// ban from community
|
||||||
|
|
||||||
let mod_ban_from_community_form = ModBanFromCommunityForm {
|
let mod_ban_from_community_form = ModBanFromCommunityForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
banned: None,
|
banned: None,
|
||||||
|
@ -447,8 +427,8 @@ mod tests {
|
||||||
let expected_mod_ban_from_community = ModBanFromCommunity {
|
let expected_mod_ban_from_community = ModBanFromCommunity {
|
||||||
id: inserted_mod_ban_from_community.id,
|
id: inserted_mod_ban_from_community.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires: None,
|
expires: None,
|
||||||
|
@ -458,8 +438,8 @@ mod tests {
|
||||||
// ban
|
// ban
|
||||||
|
|
||||||
let mod_ban_form = ModBanForm {
|
let mod_ban_form = ModBanForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
banned: None,
|
banned: None,
|
||||||
expires: None,
|
expires: None,
|
||||||
|
@ -468,8 +448,8 @@ mod tests {
|
||||||
let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap();
|
let read_mod_ban = ModBan::read(&conn, inserted_mod_ban.id).unwrap();
|
||||||
let expected_mod_ban = ModBan {
|
let expected_mod_ban = ModBan {
|
||||||
id: inserted_mod_ban.id,
|
id: inserted_mod_ban.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
reason: None,
|
reason: None,
|
||||||
banned: Some(true),
|
banned: Some(true),
|
||||||
expires: None,
|
expires: None,
|
||||||
|
@ -479,8 +459,8 @@ mod tests {
|
||||||
// mod add community
|
// mod add community
|
||||||
|
|
||||||
let mod_add_community_form = ModAddCommunityForm {
|
let mod_add_community_form = ModAddCommunityForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
};
|
};
|
||||||
|
@ -491,8 +471,8 @@ mod tests {
|
||||||
let expected_mod_add_community = ModAddCommunity {
|
let expected_mod_add_community = ModAddCommunity {
|
||||||
id: inserted_mod_add_community.id,
|
id: inserted_mod_add_community.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
removed: Some(false),
|
removed: Some(false),
|
||||||
when_: inserted_mod_add_community.when_,
|
when_: inserted_mod_add_community.when_,
|
||||||
};
|
};
|
||||||
|
@ -500,16 +480,16 @@ mod tests {
|
||||||
// mod add
|
// mod add
|
||||||
|
|
||||||
let mod_add_form = ModAddForm {
|
let mod_add_form = ModAddForm {
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
};
|
};
|
||||||
let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap();
|
let inserted_mod_add = ModAdd::create(&conn, &mod_add_form).unwrap();
|
||||||
let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap();
|
let read_mod_add = ModAdd::read(&conn, inserted_mod_add.id).unwrap();
|
||||||
let expected_mod_add = ModAdd {
|
let expected_mod_add = ModAdd {
|
||||||
id: inserted_mod_add.id,
|
id: inserted_mod_add.id,
|
||||||
mod_user_id: inserted_mod.id,
|
mod_person_id: inserted_mod.id,
|
||||||
other_user_id: inserted_user.id,
|
other_person_id: inserted_person.id,
|
||||||
removed: Some(false),
|
removed: Some(false),
|
||||||
when_: inserted_mod_add.when_,
|
when_: inserted_mod_add.when_,
|
||||||
};
|
};
|
||||||
|
@ -517,8 +497,8 @@ mod tests {
|
||||||
Comment::delete(&conn, inserted_comment.id).unwrap();
|
Comment::delete(&conn, inserted_comment.id).unwrap();
|
||||||
Post::delete(&conn, inserted_post.id).unwrap();
|
Post::delete(&conn, inserted_post.id).unwrap();
|
||||||
Community::delete(&conn, inserted_community.id).unwrap();
|
Community::delete(&conn, inserted_community.id).unwrap();
|
||||||
User_::delete(&conn, inserted_user.id).unwrap();
|
Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
User_::delete(&conn, inserted_mod.id).unwrap();
|
Person::delete(&conn, inserted_mod.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_mod_remove_post, read_mod_remove_post);
|
assert_eq!(expected_mod_remove_post, read_mod_remove_post);
|
||||||
assert_eq!(expected_mod_lock_post, read_mod_lock_post);
|
assert_eq!(expected_mod_lock_post, read_mod_lock_post);
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
use crate::Crud;
|
use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, PgConnection, *};
|
use diesel::{dsl::*, result::Error, PgConnection, *};
|
||||||
use lemmy_db_schema::{schema::password_reset_request::dsl::*, source::password_reset_request::*};
|
use lemmy_db_schema::{
|
||||||
|
schema::password_reset_request::dsl::*,
|
||||||
|
source::password_reset_request::*,
|
||||||
|
LocalUserId,
|
||||||
|
};
|
||||||
use sha2::{Digest, Sha256};
|
use sha2::{Digest, Sha256};
|
||||||
|
|
||||||
impl Crud<PasswordResetRequestForm> for PasswordResetRequest {
|
impl Crud<PasswordResetRequestForm, i32> for PasswordResetRequest {
|
||||||
fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, password_reset_request_id: i32) -> Result<Self, Error> {
|
||||||
password_reset_request
|
password_reset_request
|
||||||
.find(password_reset_request_id)
|
.find(password_reset_request_id)
|
||||||
|
@ -28,7 +32,7 @@ impl Crud<PasswordResetRequestForm> for PasswordResetRequest {
|
||||||
pub trait PasswordResetRequest_ {
|
pub trait PasswordResetRequest_ {
|
||||||
fn create_token(
|
fn create_token(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
from_user_id: i32,
|
from_local_user_id: LocalUserId,
|
||||||
token: &str,
|
token: &str,
|
||||||
) -> Result<PasswordResetRequest, Error>;
|
) -> Result<PasswordResetRequest, Error>;
|
||||||
fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error>;
|
fn read_from_token(conn: &PgConnection, token: &str) -> Result<PasswordResetRequest, Error>;
|
||||||
|
@ -37,7 +41,7 @@ pub trait PasswordResetRequest_ {
|
||||||
impl PasswordResetRequest_ for PasswordResetRequest {
|
impl PasswordResetRequest_ for PasswordResetRequest {
|
||||||
fn create_token(
|
fn create_token(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
from_user_id: i32,
|
from_local_user_id: LocalUserId,
|
||||||
token: &str,
|
token: &str,
|
||||||
) -> Result<PasswordResetRequest, Error> {
|
) -> Result<PasswordResetRequest, Error> {
|
||||||
let mut hasher = Sha256::new();
|
let mut hasher = Sha256::new();
|
||||||
|
@ -45,7 +49,7 @@ impl PasswordResetRequest_ for PasswordResetRequest {
|
||||||
let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
|
let token_hash: String = bytes_to_hex(hasher.finalize().to_vec());
|
||||||
|
|
||||||
let form = PasswordResetRequestForm {
|
let form = PasswordResetRequestForm {
|
||||||
user_id: from_user_id,
|
local_user_id: from_local_user_id,
|
||||||
token_encrypted: token_hash,
|
token_encrypted: token_hash,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -76,10 +80,12 @@ mod tests {
|
||||||
establish_unpooled_connection,
|
establish_unpooled_connection,
|
||||||
source::password_reset_request::PasswordResetRequest_,
|
source::password_reset_request::PasswordResetRequest_,
|
||||||
Crud,
|
Crud,
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
};
|
||||||
use lemmy_db_schema::source::{password_reset_request::PasswordResetRequest, user::*};
|
use lemmy_db_schema::source::{
|
||||||
|
local_user::{LocalUser, LocalUserForm},
|
||||||
|
password_reset_request::PasswordResetRequest,
|
||||||
|
person::*,
|
||||||
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -87,28 +93,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "thommy prw".into(),
|
name: "thommy prw".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -116,23 +112,40 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
|
let new_local_user = LocalUserForm {
|
||||||
|
person_id: inserted_person.id,
|
||||||
|
password_encrypted: "pass".to_string(),
|
||||||
|
email: None,
|
||||||
|
matrix_user_id: None,
|
||||||
|
admin: None,
|
||||||
|
show_nsfw: None,
|
||||||
|
theme: None,
|
||||||
|
default_sort_type: None,
|
||||||
|
default_listing_type: None,
|
||||||
|
lang: None,
|
||||||
|
show_avatars: None,
|
||||||
|
send_notifications_to_email: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let inserted_local_user = LocalUser::create(&conn, &new_local_user).unwrap();
|
||||||
|
|
||||||
let token = "nope";
|
let token = "nope";
|
||||||
let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
|
let token_encrypted_ = "ca3704aa0b06f5954c79ee837faa152d84d6b2d42838f0637a15eda8337dbdce";
|
||||||
|
|
||||||
let inserted_password_reset_request =
|
let inserted_password_reset_request =
|
||||||
PasswordResetRequest::create_token(&conn, inserted_user.id, token).unwrap();
|
PasswordResetRequest::create_token(&conn, inserted_local_user.id, token).unwrap();
|
||||||
|
|
||||||
let expected_password_reset_request = PasswordResetRequest {
|
let expected_password_reset_request = PasswordResetRequest {
|
||||||
id: inserted_password_reset_request.id,
|
id: inserted_password_reset_request.id,
|
||||||
user_id: inserted_user.id,
|
local_user_id: inserted_local_user.id,
|
||||||
token_encrypted: token_encrypted_.to_string(),
|
token_encrypted: token_encrypted_.to_string(),
|
||||||
published: inserted_password_reset_request.published,
|
published: inserted_password_reset_request.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_password_reset_request = PasswordResetRequest::read_from_token(&conn, token).unwrap();
|
let read_password_reset_request = PasswordResetRequest::read_from_token(&conn, token).unwrap();
|
||||||
let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_password_reset_request, read_password_reset_request);
|
assert_eq!(expected_password_reset_request, read_password_reset_request);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
|
|
290
crates/db_queries/src/source/person.rs
Normal file
290
crates/db_queries/src/source/person.rs
Normal file
|
@ -0,0 +1,290 @@
|
||||||
|
use crate::{ApubObject, Crud};
|
||||||
|
use diesel::{dsl::*, result::Error, *};
|
||||||
|
use lemmy_db_schema::{
|
||||||
|
naive_now,
|
||||||
|
schema::person::dsl::*,
|
||||||
|
source::person::{Person, PersonForm},
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
|
};
|
||||||
|
|
||||||
|
mod safe_type {
|
||||||
|
use crate::ToSafe;
|
||||||
|
use lemmy_db_schema::{schema::person::columns::*, source::person::Person};
|
||||||
|
|
||||||
|
type Columns = (
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl ToSafe for Person {
|
||||||
|
type SafeColumns = Columns;
|
||||||
|
fn safe_columns_tuple() -> Self::SafeColumns {
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod safe_type_alias_1 {
|
||||||
|
use crate::ToSafe;
|
||||||
|
use lemmy_db_schema::{schema::person_alias_1::columns::*, source::person::PersonAlias1};
|
||||||
|
|
||||||
|
type Columns = (
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl ToSafe for PersonAlias1 {
|
||||||
|
type SafeColumns = Columns;
|
||||||
|
fn safe_columns_tuple() -> Self::SafeColumns {
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mod safe_type_alias_2 {
|
||||||
|
use crate::ToSafe;
|
||||||
|
use lemmy_db_schema::{schema::person_alias_2::columns::*, source::person::PersonAlias2};
|
||||||
|
|
||||||
|
type Columns = (
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl ToSafe for PersonAlias2 {
|
||||||
|
type SafeColumns = Columns;
|
||||||
|
fn safe_columns_tuple() -> Self::SafeColumns {
|
||||||
|
(
|
||||||
|
id,
|
||||||
|
name,
|
||||||
|
preferred_username,
|
||||||
|
avatar,
|
||||||
|
banned,
|
||||||
|
published,
|
||||||
|
updated,
|
||||||
|
actor_id,
|
||||||
|
bio,
|
||||||
|
local,
|
||||||
|
banner,
|
||||||
|
deleted,
|
||||||
|
inbox_url,
|
||||||
|
shared_inbox_url,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Crud<PersonForm, PersonId> for Person {
|
||||||
|
fn read(conn: &PgConnection, person_id: PersonId) -> Result<Self, Error> {
|
||||||
|
person
|
||||||
|
.filter(deleted.eq(false))
|
||||||
|
.find(person_id)
|
||||||
|
.first::<Self>(conn)
|
||||||
|
}
|
||||||
|
fn delete(conn: &PgConnection, person_id: PersonId) -> Result<usize, Error> {
|
||||||
|
diesel::delete(person.find(person_id)).execute(conn)
|
||||||
|
}
|
||||||
|
fn create(conn: &PgConnection, form: &PersonForm) -> Result<Self, Error> {
|
||||||
|
insert_into(person).values(form).get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
fn update(conn: &PgConnection, person_id: PersonId, form: &PersonForm) -> Result<Self, Error> {
|
||||||
|
diesel::update(person.find(person_id))
|
||||||
|
.set(form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ApubObject<PersonForm> for Person {
|
||||||
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
|
use lemmy_db_schema::schema::person::dsl::*;
|
||||||
|
person
|
||||||
|
.filter(deleted.eq(false))
|
||||||
|
.filter(actor_id.eq(object_id))
|
||||||
|
.first::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn upsert(conn: &PgConnection, person_form: &PersonForm) -> Result<Person, Error> {
|
||||||
|
insert_into(person)
|
||||||
|
.values(person_form)
|
||||||
|
.on_conflict(actor_id)
|
||||||
|
.do_update()
|
||||||
|
.set(person_form)
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait Person_ {
|
||||||
|
fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result<Person, Error>;
|
||||||
|
fn find_by_name(conn: &PgConnection, name: &str) -> Result<Person, Error>;
|
||||||
|
fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error>;
|
||||||
|
fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Person_ for Person {
|
||||||
|
fn ban_person(conn: &PgConnection, person_id: PersonId, ban: bool) -> Result<Self, Error> {
|
||||||
|
diesel::update(person.find(person_id))
|
||||||
|
.set(banned.eq(ban))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn find_by_name(conn: &PgConnection, from_name: &str) -> Result<Person, Error> {
|
||||||
|
person
|
||||||
|
.filter(deleted.eq(false))
|
||||||
|
.filter(local.eq(true))
|
||||||
|
.filter(name.ilike(from_name))
|
||||||
|
.first::<Person>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mark_as_updated(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
|
||||||
|
diesel::update(person.find(person_id))
|
||||||
|
.set((last_refreshed_at.eq(naive_now()),))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn delete_account(conn: &PgConnection, person_id: PersonId) -> Result<Person, Error> {
|
||||||
|
use lemmy_db_schema::schema::local_user;
|
||||||
|
|
||||||
|
// Set the local user info to none
|
||||||
|
diesel::update(local_user::table.filter(local_user::person_id.eq(person_id)))
|
||||||
|
.set((
|
||||||
|
local_user::email.eq::<Option<String>>(None),
|
||||||
|
local_user::matrix_user_id.eq::<Option<String>>(None),
|
||||||
|
))
|
||||||
|
.execute(conn)?;
|
||||||
|
|
||||||
|
diesel::update(person.find(person_id))
|
||||||
|
.set((
|
||||||
|
preferred_username.eq::<Option<String>>(None),
|
||||||
|
bio.eq::<Option<String>>(None),
|
||||||
|
deleted.eq(true),
|
||||||
|
updated.eq(naive_now()),
|
||||||
|
))
|
||||||
|
.get_result::<Self>(conn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use crate::{establish_unpooled_connection, source::person::*};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_crud() {
|
||||||
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
|
let new_person = PersonForm {
|
||||||
|
name: "holly".into(),
|
||||||
|
preferred_username: None,
|
||||||
|
avatar: None,
|
||||||
|
banner: None,
|
||||||
|
banned: None,
|
||||||
|
deleted: None,
|
||||||
|
published: None,
|
||||||
|
updated: None,
|
||||||
|
actor_id: None,
|
||||||
|
bio: None,
|
||||||
|
local: None,
|
||||||
|
private_key: None,
|
||||||
|
public_key: None,
|
||||||
|
last_refreshed_at: None,
|
||||||
|
inbox_url: None,
|
||||||
|
shared_inbox_url: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
|
let expected_person = Person {
|
||||||
|
id: inserted_person.id,
|
||||||
|
name: "holly".into(),
|
||||||
|
preferred_username: None,
|
||||||
|
avatar: None,
|
||||||
|
banner: None,
|
||||||
|
banned: false,
|
||||||
|
deleted: false,
|
||||||
|
published: inserted_person.published,
|
||||||
|
updated: None,
|
||||||
|
actor_id: inserted_person.actor_id.to_owned(),
|
||||||
|
bio: None,
|
||||||
|
local: true,
|
||||||
|
private_key: None,
|
||||||
|
public_key: None,
|
||||||
|
last_refreshed_at: inserted_person.published,
|
||||||
|
inbox_url: inserted_person.inbox_url.to_owned(),
|
||||||
|
shared_inbox_url: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let read_person = Person::read(&conn, inserted_person.id).unwrap();
|
||||||
|
let updated_person = Person::update(&conn, inserted_person.id, &new_person).unwrap();
|
||||||
|
let num_deleted = Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
|
assert_eq!(expected_person, read_person);
|
||||||
|
assert_eq!(expected_person, inserted_person);
|
||||||
|
assert_eq!(expected_person, updated_person);
|
||||||
|
assert_eq!(1, num_deleted);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,68 +1,68 @@
|
||||||
use crate::Crud;
|
use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::source::user_mention::*;
|
use lemmy_db_schema::{source::person_mention::*, PersonId, PersonMentionId};
|
||||||
|
|
||||||
impl Crud<UserMentionForm> for UserMention {
|
impl Crud<PersonMentionForm, PersonMentionId> for PersonMention {
|
||||||
fn read(conn: &PgConnection, user_mention_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, person_mention_id: PersonMentionId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::user_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
user_mention.find(user_mention_id).first::<Self>(conn)
|
person_mention.find(person_mention_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create(conn: &PgConnection, user_mention_form: &UserMentionForm) -> Result<Self, Error> {
|
fn create(conn: &PgConnection, person_mention_form: &PersonMentionForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::user_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
// 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(user_mention)
|
insert_into(person_mention)
|
||||||
.values(user_mention_form)
|
.values(person_mention_form)
|
||||||
.on_conflict((recipient_id, comment_id))
|
.on_conflict((recipient_id, comment_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(user_mention_form)
|
.set(person_mention_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
user_mention_id: i32,
|
person_mention_id: PersonMentionId,
|
||||||
user_mention_form: &UserMentionForm,
|
person_mention_form: &PersonMentionForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::user_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
diesel::update(user_mention.find(user_mention_id))
|
diesel::update(person_mention.find(person_mention_id))
|
||||||
.set(user_mention_form)
|
.set(person_mention_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait UserMention_ {
|
pub trait PersonMention_ {
|
||||||
fn update_read(
|
fn update_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
user_mention_id: i32,
|
person_mention_id: PersonMentionId,
|
||||||
new_read: bool,
|
new_read: bool,
|
||||||
) -> Result<UserMention, Error>;
|
) -> Result<PersonMention, Error>;
|
||||||
fn mark_all_as_read(
|
fn mark_all_as_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_recipient_id: i32,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<Vec<UserMention>, Error>;
|
) -> Result<Vec<PersonMention>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UserMention_ for UserMention {
|
impl PersonMention_ for PersonMention {
|
||||||
fn update_read(
|
fn update_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
user_mention_id: i32,
|
person_mention_id: PersonMentionId,
|
||||||
new_read: bool,
|
new_read: bool,
|
||||||
) -> Result<UserMention, Error> {
|
) -> Result<PersonMention, Error> {
|
||||||
use lemmy_db_schema::schema::user_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
diesel::update(user_mention.find(user_mention_id))
|
diesel::update(person_mention.find(person_mention_id))
|
||||||
.set(read.eq(new_read))
|
.set(read.eq(new_read))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mark_all_as_read(
|
fn mark_all_as_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_recipient_id: i32,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<Vec<UserMention>, Error> {
|
) -> Result<Vec<PersonMention>, Error> {
|
||||||
use lemmy_db_schema::schema::user_mention::dsl::*;
|
use lemmy_db_schema::schema::person_mention::dsl::*;
|
||||||
diesel::update(
|
diesel::update(
|
||||||
user_mention
|
person_mention
|
||||||
.filter(recipient_id.eq(for_recipient_id))
|
.filter(recipient_id.eq(for_recipient_id))
|
||||||
.filter(read.eq(false)),
|
.filter(read.eq(false)),
|
||||||
)
|
)
|
||||||
|
@ -73,13 +73,13 @@ impl UserMention_ for UserMention {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{establish_unpooled_connection, Crud, ListingType, SortType};
|
use crate::{establish_unpooled_connection, Crud};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
comment::*,
|
comment::*,
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
|
person::*,
|
||||||
|
person_mention::*,
|
||||||
post::*,
|
post::*,
|
||||||
user::*,
|
|
||||||
user_mention::*,
|
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -88,28 +88,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "terrylake".into(),
|
name: "terrylake".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -117,30 +107,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let recipient_form = UserForm {
|
let recipient_form = PersonForm {
|
||||||
name: "terrylakes recipient".into(),
|
name: "terrylakes recipient".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -148,13 +128,13 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_recipient = User_::create(&conn, &recipient_form).unwrap();
|
let inserted_recipient = Person::create(&conn, &recipient_form).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "test community lake".to_string(),
|
name: "test community lake".to_string(),
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
@ -176,7 +156,7 @@ mod tests {
|
||||||
|
|
||||||
let new_post = PostForm {
|
let new_post = PostForm {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
|
@ -199,7 +179,7 @@ mod tests {
|
||||||
|
|
||||||
let comment_form = CommentForm {
|
let comment_form = CommentForm {
|
||||||
content: "A test comment".into(),
|
content: "A test comment".into(),
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -213,15 +193,15 @@ mod tests {
|
||||||
|
|
||||||
let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
|
let inserted_comment = Comment::create(&conn, &comment_form).unwrap();
|
||||||
|
|
||||||
let user_mention_form = UserMentionForm {
|
let person_mention_form = PersonMentionForm {
|
||||||
recipient_id: inserted_recipient.id,
|
recipient_id: inserted_recipient.id,
|
||||||
comment_id: inserted_comment.id,
|
comment_id: inserted_comment.id,
|
||||||
read: None,
|
read: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_mention = UserMention::create(&conn, &user_mention_form).unwrap();
|
let inserted_mention = PersonMention::create(&conn, &person_mention_form).unwrap();
|
||||||
|
|
||||||
let expected_mention = UserMention {
|
let expected_mention = PersonMention {
|
||||||
id: inserted_mention.id,
|
id: inserted_mention.id,
|
||||||
recipient_id: inserted_mention.recipient_id,
|
recipient_id: inserted_mention.recipient_id,
|
||||||
comment_id: inserted_mention.comment_id,
|
comment_id: inserted_mention.comment_id,
|
||||||
|
@ -229,14 +209,14 @@ mod tests {
|
||||||
published: inserted_mention.published,
|
published: inserted_mention.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_mention = UserMention::read(&conn, inserted_mention.id).unwrap();
|
let read_mention = PersonMention::read(&conn, inserted_mention.id).unwrap();
|
||||||
let updated_mention =
|
let updated_mention =
|
||||||
UserMention::update(&conn, inserted_mention.id, &user_mention_form).unwrap();
|
PersonMention::update(&conn, inserted_mention.id, &person_mention_form).unwrap();
|
||||||
Comment::delete(&conn, inserted_comment.id).unwrap();
|
Comment::delete(&conn, inserted_comment.id).unwrap();
|
||||||
Post::delete(&conn, inserted_post.id).unwrap();
|
Post::delete(&conn, inserted_post.id).unwrap();
|
||||||
Community::delete(&conn, inserted_community.id).unwrap();
|
Community::delete(&conn, inserted_community.id).unwrap();
|
||||||
User_::delete(&conn, inserted_user.id).unwrap();
|
Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
User_::delete(&conn, inserted_recipient.id).unwrap();
|
Person::delete(&conn, inserted_recipient.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_mention, read_mention);
|
assert_eq!(expected_mention, read_mention);
|
||||||
assert_eq!(expected_mention, inserted_mention);
|
assert_eq!(expected_mention, inserted_mention);
|
|
@ -12,16 +12,19 @@ use lemmy_db_schema::{
|
||||||
PostSaved,
|
PostSaved,
|
||||||
PostSavedForm,
|
PostSavedForm,
|
||||||
},
|
},
|
||||||
Url,
|
CommunityId,
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
|
PostId,
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Crud<PostForm> for Post {
|
impl Crud<PostForm, PostId> for Post {
|
||||||
fn read(conn: &PgConnection, post_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, post_id: PostId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post.find(post_id).first::<Self>(conn)
|
post.find(post_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn delete(conn: &PgConnection, post_id: i32) -> Result<usize, Error> {
|
fn delete(conn: &PgConnection, post_id: PostId) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::delete(post.find(post_id)).execute(conn)
|
diesel::delete(post.find(post_id)).execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -31,7 +34,7 @@ impl Crud<PostForm> for Post {
|
||||||
insert_into(post).values(new_post).get_result::<Self>(conn)
|
insert_into(post).values(new_post).get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(conn: &PgConnection, post_id: i32, new_post: &PostForm) -> Result<Self, Error> {
|
fn update(conn: &PgConnection, post_id: PostId, new_post: &PostForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
.set(new_post)
|
.set(new_post)
|
||||||
|
@ -41,24 +44,39 @@ impl Crud<PostForm> for Post {
|
||||||
|
|
||||||
pub trait Post_ {
|
pub trait Post_ {
|
||||||
//fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
|
//fn read(conn: &PgConnection, post_id: i32) -> Result<Post, Error>;
|
||||||
fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Post>, Error>;
|
fn list_for_community(
|
||||||
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: Url) -> Result<Post, Error>;
|
conn: &PgConnection,
|
||||||
fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Post>, Error>;
|
the_community_id: CommunityId,
|
||||||
fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Post, Error>;
|
) -> Result<Vec<Post>, Error>;
|
||||||
fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Post, Error>;
|
fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result<Post, Error>;
|
||||||
|
fn permadelete_for_creator(
|
||||||
|
conn: &PgConnection,
|
||||||
|
for_creator_id: PersonId,
|
||||||
|
) -> Result<Vec<Post>, Error>;
|
||||||
|
fn update_deleted(conn: &PgConnection, post_id: PostId, new_deleted: bool)
|
||||||
|
-> Result<Post, Error>;
|
||||||
|
fn update_removed(conn: &PgConnection, post_id: PostId, new_removed: bool)
|
||||||
|
-> Result<Post, Error>;
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
for_community_id: Option<i32>,
|
for_community_id: Option<CommunityId>,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Post>, Error>;
|
) -> Result<Vec<Post>, Error>;
|
||||||
fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Post, Error>;
|
fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result<Post, Error>;
|
||||||
fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Post, Error>;
|
fn update_stickied(
|
||||||
fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool;
|
conn: &PgConnection,
|
||||||
|
post_id: PostId,
|
||||||
|
new_stickied: bool,
|
||||||
|
) -> Result<Post, Error>;
|
||||||
|
fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Post_ for Post {
|
impl Post_ for Post {
|
||||||
fn list_for_community(conn: &PgConnection, the_community_id: i32) -> Result<Vec<Self>, Error> {
|
fn list_for_community(
|
||||||
|
conn: &PgConnection,
|
||||||
|
the_community_id: CommunityId,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post
|
post
|
||||||
.filter(community_id.eq(the_community_id))
|
.filter(community_id.eq(the_community_id))
|
||||||
|
@ -68,7 +86,7 @@ impl Post_ for Post {
|
||||||
.load::<Self>(conn)
|
.load::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_ap_id(conn: &PgConnection, post_id: i32, apub_id: Url) -> Result<Self, Error> {
|
fn update_ap_id(conn: &PgConnection, post_id: PostId, apub_id: DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
|
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
|
@ -76,7 +94,10 @@ impl Post_ for Post {
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn permadelete_for_creator(conn: &PgConnection, for_creator_id: i32) -> Result<Vec<Self>, Error> {
|
fn permadelete_for_creator(
|
||||||
|
conn: &PgConnection,
|
||||||
|
for_creator_id: PersonId,
|
||||||
|
) -> Result<Vec<Self>, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
|
|
||||||
let perma_deleted = "*Permananently Deleted*";
|
let perma_deleted = "*Permananently Deleted*";
|
||||||
|
@ -93,14 +114,22 @@ impl Post_ for Post {
|
||||||
.get_results::<Self>(conn)
|
.get_results::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_deleted(conn: &PgConnection, post_id: i32, new_deleted: bool) -> Result<Self, Error> {
|
fn update_deleted(
|
||||||
|
conn: &PgConnection,
|
||||||
|
post_id: PostId,
|
||||||
|
new_deleted: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
.set((deleted.eq(new_deleted), updated.eq(naive_now())))
|
.set((deleted.eq(new_deleted), updated.eq(naive_now())))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_removed(conn: &PgConnection, post_id: i32, new_removed: bool) -> Result<Self, Error> {
|
fn update_removed(
|
||||||
|
conn: &PgConnection,
|
||||||
|
post_id: PostId,
|
||||||
|
new_removed: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
.set((removed.eq(new_removed), updated.eq(naive_now())))
|
.set((removed.eq(new_removed), updated.eq(naive_now())))
|
||||||
|
@ -109,8 +138,8 @@ impl Post_ for Post {
|
||||||
|
|
||||||
fn update_removed_for_creator(
|
fn update_removed_for_creator(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_creator_id: i32,
|
for_creator_id: PersonId,
|
||||||
for_community_id: Option<i32>,
|
for_community_id: Option<CommunityId>,
|
||||||
new_removed: bool,
|
new_removed: bool,
|
||||||
) -> Result<Vec<Self>, Error> {
|
) -> Result<Vec<Self>, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
|
@ -127,27 +156,31 @@ impl Post_ for Post {
|
||||||
.get_results::<Self>(conn)
|
.get_results::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_locked(conn: &PgConnection, post_id: i32, new_locked: bool) -> Result<Self, Error> {
|
fn update_locked(conn: &PgConnection, post_id: PostId, new_locked: bool) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
.set(locked.eq(new_locked))
|
.set(locked.eq(new_locked))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update_stickied(conn: &PgConnection, post_id: i32, new_stickied: bool) -> Result<Self, Error> {
|
fn update_stickied(
|
||||||
|
conn: &PgConnection,
|
||||||
|
post_id: PostId,
|
||||||
|
new_stickied: bool,
|
||||||
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
diesel::update(post.find(post_id))
|
diesel::update(post.find(post_id))
|
||||||
.set(stickied.eq(new_stickied))
|
.set(stickied.eq(new_stickied))
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_post_creator(user_id: i32, post_creator_id: i32) -> bool {
|
fn is_post_creator(person_id: PersonId, post_creator_id: PersonId) -> bool {
|
||||||
user_id == post_creator_id
|
person_id == post_creator_id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PostForm> for Post {
|
impl ApubObject<PostForm> for Post {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post::dsl::*;
|
use lemmy_db_schema::schema::post::dsl::*;
|
||||||
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
post.filter(ap_id.eq(object_id)).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
@ -163,22 +196,22 @@ impl ApubObject<PostForm> for Post {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Likeable<PostLikeForm> for PostLike {
|
impl Likeable<PostLikeForm, PostId> for PostLike {
|
||||||
fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
|
fn like(conn: &PgConnection, post_like_form: &PostLikeForm) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::post_like::dsl::*;
|
use lemmy_db_schema::schema::post_like::dsl::*;
|
||||||
insert_into(post_like)
|
insert_into(post_like)
|
||||||
.values(post_like_form)
|
.values(post_like_form)
|
||||||
.on_conflict((post_id, user_id))
|
.on_conflict((post_id, person_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(post_like_form)
|
.set(post_like_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
}
|
}
|
||||||
fn remove(conn: &PgConnection, user_id: i32, post_id: i32) -> Result<usize, Error> {
|
fn remove(conn: &PgConnection, person_id: PersonId, post_id: PostId) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::post_like::dsl;
|
use lemmy_db_schema::schema::post_like::dsl;
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
dsl::post_like
|
dsl::post_like
|
||||||
.filter(dsl::post_id.eq(post_id))
|
.filter(dsl::post_id.eq(post_id))
|
||||||
.filter(dsl::user_id.eq(user_id)),
|
.filter(dsl::person_id.eq(person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -189,7 +222,7 @@ impl Saveable<PostSavedForm> for PostSaved {
|
||||||
use lemmy_db_schema::schema::post_saved::dsl::*;
|
use lemmy_db_schema::schema::post_saved::dsl::*;
|
||||||
insert_into(post_saved)
|
insert_into(post_saved)
|
||||||
.values(post_saved_form)
|
.values(post_saved_form)
|
||||||
.on_conflict((post_id, user_id))
|
.on_conflict((post_id, person_id))
|
||||||
.do_update()
|
.do_update()
|
||||||
.set(post_saved_form)
|
.set(post_saved_form)
|
||||||
.get_result::<Self>(conn)
|
.get_result::<Self>(conn)
|
||||||
|
@ -199,7 +232,7 @@ impl Saveable<PostSavedForm> for PostSaved {
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
post_saved
|
post_saved
|
||||||
.filter(post_id.eq(post_saved_form.post_id))
|
.filter(post_id.eq(post_saved_form.post_id))
|
||||||
.filter(user_id.eq(post_saved_form.user_id)),
|
.filter(person_id.eq(post_saved_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -218,7 +251,7 @@ impl Readable<PostReadForm> for PostRead {
|
||||||
diesel::delete(
|
diesel::delete(
|
||||||
post_read
|
post_read
|
||||||
.filter(post_id.eq(post_read_form.post_id))
|
.filter(post_id.eq(post_read_form.post_id))
|
||||||
.filter(user_id.eq(post_read_form.user_id)),
|
.filter(person_id.eq(post_read_form.person_id)),
|
||||||
)
|
)
|
||||||
.execute(conn)
|
.execute(conn)
|
||||||
}
|
}
|
||||||
|
@ -226,10 +259,10 @@ impl Readable<PostReadForm> for PostRead {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{establish_unpooled_connection, source::post::*, ListingType, SortType};
|
use crate::{establish_unpooled_connection, source::post::*};
|
||||||
use lemmy_db_schema::source::{
|
use lemmy_db_schema::source::{
|
||||||
community::{Community, CommunityForm},
|
community::{Community, CommunityForm},
|
||||||
user::*,
|
person::*,
|
||||||
};
|
};
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
|
@ -238,28 +271,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let new_user = UserForm {
|
let new_person = PersonForm {
|
||||||
name: "jim".into(),
|
name: "jim".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -267,13 +290,13 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
let inserted_person = Person::create(&conn, &new_person).unwrap();
|
||||||
|
|
||||||
let new_community = CommunityForm {
|
let new_community = CommunityForm {
|
||||||
name: "test community_3".to_string(),
|
name: "test community_3".to_string(),
|
||||||
title: "nada".to_owned(),
|
title: "nada".to_owned(),
|
||||||
description: None,
|
description: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
|
@ -297,7 +320,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
removed: None,
|
removed: None,
|
||||||
deleted: None,
|
deleted: None,
|
||||||
|
@ -321,7 +344,7 @@ mod tests {
|
||||||
name: "A test post".into(),
|
name: "A test post".into(),
|
||||||
url: None,
|
url: None,
|
||||||
body: None,
|
body: None,
|
||||||
creator_id: inserted_user.id,
|
creator_id: inserted_person.id,
|
||||||
community_id: inserted_community.id,
|
community_id: inserted_community.id,
|
||||||
published: inserted_post.published,
|
published: inserted_post.published,
|
||||||
removed: false,
|
removed: false,
|
||||||
|
@ -341,7 +364,7 @@ mod tests {
|
||||||
// Post Like
|
// Post Like
|
||||||
let post_like_form = PostLikeForm {
|
let post_like_form = PostLikeForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -350,7 +373,7 @@ mod tests {
|
||||||
let expected_post_like = PostLike {
|
let expected_post_like = PostLike {
|
||||||
id: inserted_post_like.id,
|
id: inserted_post_like.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_post_like.published,
|
published: inserted_post_like.published,
|
||||||
score: 1,
|
score: 1,
|
||||||
};
|
};
|
||||||
|
@ -358,7 +381,7 @@ mod tests {
|
||||||
// Post Save
|
// Post Save
|
||||||
let post_saved_form = PostSavedForm {
|
let post_saved_form = PostSavedForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap();
|
let inserted_post_saved = PostSaved::save(&conn, &post_saved_form).unwrap();
|
||||||
|
@ -366,14 +389,14 @@ mod tests {
|
||||||
let expected_post_saved = PostSaved {
|
let expected_post_saved = PostSaved {
|
||||||
id: inserted_post_saved.id,
|
id: inserted_post_saved.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_post_saved.published,
|
published: inserted_post_saved.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Post Read
|
// Post Read
|
||||||
let post_read_form = PostReadForm {
|
let post_read_form = PostReadForm {
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap();
|
let inserted_post_read = PostRead::mark_as_read(&conn, &post_read_form).unwrap();
|
||||||
|
@ -381,18 +404,18 @@ mod tests {
|
||||||
let expected_post_read = PostRead {
|
let expected_post_read = PostRead {
|
||||||
id: inserted_post_read.id,
|
id: inserted_post_read.id,
|
||||||
post_id: inserted_post.id,
|
post_id: inserted_post.id,
|
||||||
user_id: inserted_user.id,
|
person_id: inserted_person.id,
|
||||||
published: inserted_post_read.published,
|
published: inserted_post_read.published,
|
||||||
};
|
};
|
||||||
|
|
||||||
let read_post = Post::read(&conn, inserted_post.id).unwrap();
|
let read_post = Post::read(&conn, inserted_post.id).unwrap();
|
||||||
let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
|
let updated_post = Post::update(&conn, inserted_post.id, &new_post).unwrap();
|
||||||
let like_removed = PostLike::remove(&conn, inserted_user.id, inserted_post.id).unwrap();
|
let like_removed = PostLike::remove(&conn, inserted_person.id, inserted_post.id).unwrap();
|
||||||
let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap();
|
let saved_removed = PostSaved::unsave(&conn, &post_saved_form).unwrap();
|
||||||
let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap();
|
let read_removed = PostRead::mark_as_unread(&conn, &post_read_form).unwrap();
|
||||||
let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
|
let num_deleted = Post::delete(&conn, inserted_post.id).unwrap();
|
||||||
Community::delete(&conn, inserted_community.id).unwrap();
|
Community::delete(&conn, inserted_community.id).unwrap();
|
||||||
User_::delete(&conn, inserted_user.id).unwrap();
|
Person::delete(&conn, inserted_person.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_post, read_post);
|
assert_eq!(expected_post, read_post);
|
||||||
assert_eq!(expected_post, inserted_post);
|
assert_eq!(expected_post, inserted_post);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::Reportable;
|
use crate::Reportable;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::post_report::*};
|
use lemmy_db_schema::{naive_now, source::post_report::*, PersonId};
|
||||||
|
|
||||||
impl Reportable<PostReportForm> for PostReport {
|
impl Reportable<PostReportForm> for PostReport {
|
||||||
/// creates a post report and returns it
|
/// creates a post report and returns it
|
||||||
|
@ -19,7 +19,11 @@ impl Reportable<PostReportForm> for PostReport {
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
/// * `report_id` - the id of the report to resolve
|
/// * `report_id` - the id of the report to resolve
|
||||||
/// * `by_resolver_id` - the id of the user resolving the report
|
/// * `by_resolver_id` - the id of the user resolving the report
|
||||||
fn resolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result<usize, Error> {
|
fn resolve(
|
||||||
|
conn: &PgConnection,
|
||||||
|
report_id: i32,
|
||||||
|
by_resolver_id: PersonId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::post_report::dsl::*;
|
use lemmy_db_schema::schema::post_report::dsl::*;
|
||||||
update(post_report.find(report_id))
|
update(post_report.find(report_id))
|
||||||
.set((
|
.set((
|
||||||
|
@ -35,7 +39,11 @@ impl Reportable<PostReportForm> for PostReport {
|
||||||
/// * `conn` - the postgres connection
|
/// * `conn` - the postgres connection
|
||||||
/// * `report_id` - the id of the report to unresolve
|
/// * `report_id` - the id of the report to unresolve
|
||||||
/// * `by_resolver_id` - the id of the user unresolving the report
|
/// * `by_resolver_id` - the id of the user unresolving the report
|
||||||
fn unresolve(conn: &PgConnection, report_id: i32, by_resolver_id: i32) -> Result<usize, Error> {
|
fn unresolve(
|
||||||
|
conn: &PgConnection,
|
||||||
|
report_id: i32,
|
||||||
|
by_resolver_id: PersonId,
|
||||||
|
) -> Result<usize, Error> {
|
||||||
use lemmy_db_schema::schema::post_report::dsl::*;
|
use lemmy_db_schema::schema::post_report::dsl::*;
|
||||||
update(post_report.find(report_id))
|
update(post_report.find(report_id))
|
||||||
.set((
|
.set((
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
use crate::{ApubObject, Crud};
|
use crate::{ApubObject, Crud};
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::private_message::*, Url};
|
use lemmy_db_schema::{naive_now, source::private_message::*, DbUrl, PersonId, PrivateMessageId};
|
||||||
|
|
||||||
impl Crud<PrivateMessageForm> for PrivateMessage {
|
impl Crud<PrivateMessageForm, PrivateMessageId> for PrivateMessage {
|
||||||
fn read(conn: &PgConnection, private_message_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, private_message_id: PrivateMessageId) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
private_message.find(private_message_id).first::<Self>(conn)
|
private_message.find(private_message_id).first::<Self>(conn)
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ impl Crud<PrivateMessageForm> for PrivateMessage {
|
||||||
|
|
||||||
fn update(
|
fn update(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
private_message_form: &PrivateMessageForm,
|
private_message_form: &PrivateMessageForm,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
@ -28,7 +28,7 @@ impl Crud<PrivateMessageForm> for PrivateMessage {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error>
|
fn read_from_apub_id(conn: &PgConnection, object_id: &DbUrl) -> Result<Self, Error>
|
||||||
where
|
where
|
||||||
Self: Sized,
|
Self: Sized,
|
||||||
{
|
{
|
||||||
|
@ -52,35 +52,35 @@ impl ApubObject<PrivateMessageForm> for PrivateMessage {
|
||||||
pub trait PrivateMessage_ {
|
pub trait PrivateMessage_ {
|
||||||
fn update_ap_id(
|
fn update_ap_id(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
apub_id: Url,
|
apub_id: DbUrl,
|
||||||
) -> Result<PrivateMessage, Error>;
|
) -> Result<PrivateMessage, Error>;
|
||||||
fn update_content(
|
fn update_content(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_content: &str,
|
new_content: &str,
|
||||||
) -> Result<PrivateMessage, Error>;
|
) -> Result<PrivateMessage, Error>;
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<PrivateMessage, Error>;
|
) -> Result<PrivateMessage, Error>;
|
||||||
fn update_read(
|
fn update_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_read: bool,
|
new_read: bool,
|
||||||
) -> Result<PrivateMessage, Error>;
|
) -> Result<PrivateMessage, Error>;
|
||||||
fn mark_all_as_read(
|
fn mark_all_as_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_recipient_id: i32,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<Vec<PrivateMessage>, Error>;
|
) -> Result<Vec<PrivateMessage>, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl PrivateMessage_ for PrivateMessage {
|
impl PrivateMessage_ for PrivateMessage {
|
||||||
fn update_ap_id(
|
fn update_ap_id(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
apub_id: Url,
|
apub_id: DbUrl,
|
||||||
) -> Result<PrivateMessage, Error> {
|
) -> Result<PrivateMessage, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
|
|
||||||
fn update_content(
|
fn update_content(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_content: &str,
|
new_content: &str,
|
||||||
) -> Result<PrivateMessage, Error> {
|
) -> Result<PrivateMessage, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
@ -102,7 +102,7 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
|
|
||||||
fn update_deleted(
|
fn update_deleted(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_deleted: bool,
|
new_deleted: bool,
|
||||||
) -> Result<PrivateMessage, Error> {
|
) -> Result<PrivateMessage, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
@ -113,7 +113,7 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
|
|
||||||
fn update_read(
|
fn update_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
private_message_id: i32,
|
private_message_id: PrivateMessageId,
|
||||||
new_read: bool,
|
new_read: bool,
|
||||||
) -> Result<PrivateMessage, Error> {
|
) -> Result<PrivateMessage, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
|
@ -124,7 +124,7 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
|
|
||||||
fn mark_all_as_read(
|
fn mark_all_as_read(
|
||||||
conn: &PgConnection,
|
conn: &PgConnection,
|
||||||
for_recipient_id: i32,
|
for_recipient_id: PersonId,
|
||||||
) -> Result<Vec<PrivateMessage>, Error> {
|
) -> Result<Vec<PrivateMessage>, Error> {
|
||||||
use lemmy_db_schema::schema::private_message::dsl::*;
|
use lemmy_db_schema::schema::private_message::dsl::*;
|
||||||
diesel::update(
|
diesel::update(
|
||||||
|
@ -139,14 +139,8 @@ impl PrivateMessage_ for PrivateMessage {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use crate::{
|
use crate::{establish_unpooled_connection, source::private_message::PrivateMessage_, Crud};
|
||||||
establish_unpooled_connection,
|
use lemmy_db_schema::source::{person::*, private_message::*};
|
||||||
source::private_message::PrivateMessage_,
|
|
||||||
Crud,
|
|
||||||
ListingType,
|
|
||||||
SortType,
|
|
||||||
};
|
|
||||||
use lemmy_db_schema::source::{private_message::*, user::*};
|
|
||||||
use serial_test::serial;
|
use serial_test::serial;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -154,28 +148,18 @@ mod tests {
|
||||||
fn test_crud() {
|
fn test_crud() {
|
||||||
let conn = establish_unpooled_connection();
|
let conn = establish_unpooled_connection();
|
||||||
|
|
||||||
let creator_form = UserForm {
|
let creator_form = PersonForm {
|
||||||
name: "creator_pm".into(),
|
name: "creator_pm".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -183,30 +167,20 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_creator = User_::create(&conn, &creator_form).unwrap();
|
let inserted_creator = Person::create(&conn, &creator_form).unwrap();
|
||||||
|
|
||||||
let recipient_form = UserForm {
|
let recipient_form = PersonForm {
|
||||||
name: "recipient_pm".into(),
|
name: "recipient_pm".into(),
|
||||||
preferred_username: None,
|
preferred_username: None,
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
avatar: None,
|
||||||
banner: None,
|
banner: None,
|
||||||
admin: false,
|
banned: None,
|
||||||
banned: Some(false),
|
deleted: None,
|
||||||
published: None,
|
published: None,
|
||||||
updated: None,
|
updated: None,
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
actor_id: None,
|
||||||
bio: None,
|
bio: None,
|
||||||
local: true,
|
local: None,
|
||||||
private_key: None,
|
private_key: None,
|
||||||
public_key: None,
|
public_key: None,
|
||||||
last_refreshed_at: None,
|
last_refreshed_at: None,
|
||||||
|
@ -214,7 +188,7 @@ mod tests {
|
||||||
shared_inbox_url: None,
|
shared_inbox_url: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let inserted_recipient = User_::create(&conn, &recipient_form).unwrap();
|
let inserted_recipient = Person::create(&conn, &recipient_form).unwrap();
|
||||||
|
|
||||||
let private_message_form = PrivateMessageForm {
|
let private_message_form = PrivateMessageForm {
|
||||||
content: "A test private message".into(),
|
content: "A test private message".into(),
|
||||||
|
@ -250,8 +224,8 @@ mod tests {
|
||||||
PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap();
|
PrivateMessage::update_deleted(&conn, inserted_private_message.id, true).unwrap();
|
||||||
let marked_read_private_message =
|
let marked_read_private_message =
|
||||||
PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap();
|
PrivateMessage::update_read(&conn, inserted_private_message.id, true).unwrap();
|
||||||
User_::delete(&conn, inserted_creator.id).unwrap();
|
Person::delete(&conn, inserted_creator.id).unwrap();
|
||||||
User_::delete(&conn, inserted_recipient.id).unwrap();
|
Person::delete(&conn, inserted_recipient.id).unwrap();
|
||||||
|
|
||||||
assert_eq!(expected_private_message, read_private_message);
|
assert_eq!(expected_private_message, read_private_message);
|
||||||
assert_eq!(expected_private_message, updated_private_message);
|
assert_eq!(expected_private_message, updated_private_message);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
use crate::Crud;
|
use crate::Crud;
|
||||||
use diesel::{dsl::*, result::Error, *};
|
use diesel::{dsl::*, result::Error, *};
|
||||||
use lemmy_db_schema::{naive_now, source::site::*};
|
use lemmy_db_schema::{naive_now, source::site::*, PersonId};
|
||||||
|
|
||||||
impl Crud<SiteForm> for Site {
|
impl Crud<SiteForm, i32> for Site {
|
||||||
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
fn read(conn: &PgConnection, _site_id: i32) -> Result<Self, Error> {
|
||||||
use lemmy_db_schema::schema::site::dsl::*;
|
use lemmy_db_schema::schema::site::dsl::*;
|
||||||
site.first::<Self>(conn)
|
site.first::<Self>(conn)
|
||||||
|
@ -26,12 +26,12 @@ impl Crud<SiteForm> for Site {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Site_ {
|
pub trait Site_ {
|
||||||
fn transfer(conn: &PgConnection, new_creator_id: i32) -> Result<Site, Error>;
|
fn transfer(conn: &PgConnection, new_creator_id: PersonId) -> Result<Site, Error>;
|
||||||
fn read_simple(conn: &PgConnection) -> Result<Site, Error>;
|
fn read_simple(conn: &PgConnection) -> Result<Site, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Site_ for Site {
|
impl Site_ for Site {
|
||||||
fn transfer(conn: &PgConnection, new_creator_id: i32) -> Result<Site, Error> {
|
fn transfer(conn: &PgConnection, new_creator_id: PersonId) -> Result<Site, Error> {
|
||||||
use lemmy_db_schema::schema::site::dsl::*;
|
use lemmy_db_schema::schema::site::dsl::*;
|
||||||
diesel::update(site.find(1))
|
diesel::update(site.find(1))
|
||||||
.set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
|
.set((creator_id.eq(new_creator_id), updated.eq(naive_now())))
|
||||||
|
|
|
@ -1,460 +0,0 @@
|
||||||
use crate::{is_email_regex, ApubObject, Crud, ToSafeSettings};
|
|
||||||
use bcrypt::{hash, DEFAULT_COST};
|
|
||||||
use diesel::{dsl::*, result::Error, *};
|
|
||||||
use lemmy_db_schema::{
|
|
||||||
naive_now,
|
|
||||||
schema::user_::dsl::*,
|
|
||||||
source::user::{UserForm, UserSafeSettings, User_},
|
|
||||||
Url,
|
|
||||||
};
|
|
||||||
use lemmy_utils::settings::structs::Settings;
|
|
||||||
|
|
||||||
mod safe_type {
|
|
||||||
use crate::ToSafe;
|
|
||||||
use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
|
|
||||||
|
|
||||||
type Columns = (
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
inbox_url,
|
|
||||||
shared_inbox_url,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ToSafe for User_ {
|
|
||||||
type SafeColumns = Columns;
|
|
||||||
fn safe_columns_tuple() -> Self::SafeColumns {
|
|
||||||
(
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
inbox_url,
|
|
||||||
shared_inbox_url,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod safe_type_alias_1 {
|
|
||||||
use crate::ToSafe;
|
|
||||||
use lemmy_db_schema::{schema::user_alias_1::columns::*, source::user::UserAlias1};
|
|
||||||
|
|
||||||
type Columns = (
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ToSafe for UserAlias1 {
|
|
||||||
type SafeColumns = Columns;
|
|
||||||
fn safe_columns_tuple() -> Self::SafeColumns {
|
|
||||||
(
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod safe_type_alias_2 {
|
|
||||||
use crate::ToSafe;
|
|
||||||
use lemmy_db_schema::{schema::user_alias_2::columns::*, source::user::UserAlias2};
|
|
||||||
|
|
||||||
type Columns = (
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ToSafe for UserAlias2 {
|
|
||||||
type SafeColumns = Columns;
|
|
||||||
fn safe_columns_tuple() -> Self::SafeColumns {
|
|
||||||
(
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mod safe_settings_type {
|
|
||||||
use crate::ToSafeSettings;
|
|
||||||
use lemmy_db_schema::{schema::user_::columns::*, source::user::User_};
|
|
||||||
|
|
||||||
type Columns = (
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
email,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
show_nsfw,
|
|
||||||
theme,
|
|
||||||
default_sort_type,
|
|
||||||
default_listing_type,
|
|
||||||
lang,
|
|
||||||
show_avatars,
|
|
||||||
send_notifications_to_email,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
last_refreshed_at,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
);
|
|
||||||
|
|
||||||
impl ToSafeSettings for User_ {
|
|
||||||
type SafeSettingsColumns = Columns;
|
|
||||||
fn safe_settings_columns_tuple() -> Self::SafeSettingsColumns {
|
|
||||||
(
|
|
||||||
id,
|
|
||||||
name,
|
|
||||||
preferred_username,
|
|
||||||
email,
|
|
||||||
avatar,
|
|
||||||
admin,
|
|
||||||
banned,
|
|
||||||
published,
|
|
||||||
updated,
|
|
||||||
show_nsfw,
|
|
||||||
theme,
|
|
||||||
default_sort_type,
|
|
||||||
default_listing_type,
|
|
||||||
lang,
|
|
||||||
show_avatars,
|
|
||||||
send_notifications_to_email,
|
|
||||||
matrix_user_id,
|
|
||||||
actor_id,
|
|
||||||
bio,
|
|
||||||
local,
|
|
||||||
last_refreshed_at,
|
|
||||||
banner,
|
|
||||||
deleted,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait UserSafeSettings_ {
|
|
||||||
fn read(conn: &PgConnection, user_id: i32) -> Result<UserSafeSettings, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl UserSafeSettings_ for UserSafeSettings {
|
|
||||||
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
|
|
||||||
user_
|
|
||||||
.select(User_::safe_settings_columns_tuple())
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.find(user_id)
|
|
||||||
.first::<Self>(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Crud<UserForm> for User_ {
|
|
||||||
fn read(conn: &PgConnection, user_id: i32) -> Result<Self, Error> {
|
|
||||||
user_
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.find(user_id)
|
|
||||||
.first::<Self>(conn)
|
|
||||||
}
|
|
||||||
fn delete(conn: &PgConnection, user_id: i32) -> Result<usize, Error> {
|
|
||||||
diesel::delete(user_.find(user_id)).execute(conn)
|
|
||||||
}
|
|
||||||
fn create(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
|
|
||||||
insert_into(user_).values(form).get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
fn update(conn: &PgConnection, user_id: i32, form: &UserForm) -> Result<Self, Error> {
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set(form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ApubObject<UserForm> for User_ {
|
|
||||||
fn read_from_apub_id(conn: &PgConnection, object_id: &Url) -> Result<Self, Error> {
|
|
||||||
use lemmy_db_schema::schema::user_::dsl::*;
|
|
||||||
user_
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(actor_id.eq(object_id))
|
|
||||||
.first::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn upsert(conn: &PgConnection, user_form: &UserForm) -> Result<User_, Error> {
|
|
||||||
insert_into(user_)
|
|
||||||
.values(user_form)
|
|
||||||
.on_conflict(actor_id)
|
|
||||||
.do_update()
|
|
||||||
.set(user_form)
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait User {
|
|
||||||
fn register(conn: &PgConnection, form: &UserForm) -> Result<User_, Error>;
|
|
||||||
fn update_password(conn: &PgConnection, user_id: i32, new_password: &str)
|
|
||||||
-> Result<User_, Error>;
|
|
||||||
fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<User_, Error>;
|
|
||||||
fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<User_, Error>;
|
|
||||||
fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<User_, Error>;
|
|
||||||
fn find_by_email_or_username(
|
|
||||||
conn: &PgConnection,
|
|
||||||
username_or_email: &str,
|
|
||||||
) -> Result<User_, Error>;
|
|
||||||
fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error>;
|
|
||||||
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error>;
|
|
||||||
fn get_profile_url(&self, hostname: &str) -> String;
|
|
||||||
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
|
|
||||||
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error>;
|
|
||||||
}
|
|
||||||
|
|
||||||
impl User for User_ {
|
|
||||||
fn register(conn: &PgConnection, form: &UserForm) -> Result<Self, Error> {
|
|
||||||
let mut edited_user = form.clone();
|
|
||||||
let password_hash =
|
|
||||||
hash(&form.password_encrypted, DEFAULT_COST).expect("Couldn't hash password");
|
|
||||||
edited_user.password_encrypted = password_hash;
|
|
||||||
|
|
||||||
Self::create(&conn, &edited_user)
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO do more individual updates like these
|
|
||||||
fn update_password(conn: &PgConnection, user_id: i32, new_password: &str) -> Result<Self, Error> {
|
|
||||||
let password_hash = hash(new_password, DEFAULT_COST).expect("Couldn't hash password");
|
|
||||||
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set((
|
|
||||||
password_encrypted.eq(password_hash),
|
|
||||||
updated.eq(naive_now()),
|
|
||||||
))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn read_from_name(conn: &PgConnection, from_user_name: &str) -> Result<Self, Error> {
|
|
||||||
user_
|
|
||||||
.filter(local.eq(true))
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(name.eq(from_user_name))
|
|
||||||
.first::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn add_admin(conn: &PgConnection, user_id: i32, added: bool) -> Result<Self, Error> {
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set(admin.eq(added))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn ban_user(conn: &PgConnection, user_id: i32, ban: bool) -> Result<Self, Error> {
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set(banned.eq(ban))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_by_email_or_username(
|
|
||||||
conn: &PgConnection,
|
|
||||||
username_or_email: &str,
|
|
||||||
) -> Result<Self, Error> {
|
|
||||||
if is_email_regex(username_or_email) {
|
|
||||||
Self::find_by_email(conn, username_or_email)
|
|
||||||
} else {
|
|
||||||
Self::find_by_username(conn, username_or_email)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_by_username(conn: &PgConnection, username: &str) -> Result<User_, Error> {
|
|
||||||
user_
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(local.eq(true))
|
|
||||||
.filter(name.ilike(username))
|
|
||||||
.first::<User_>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn find_by_email(conn: &PgConnection, from_email: &str) -> Result<User_, Error> {
|
|
||||||
user_
|
|
||||||
.filter(deleted.eq(false))
|
|
||||||
.filter(local.eq(true))
|
|
||||||
.filter(email.eq(from_email))
|
|
||||||
.first::<User_>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_profile_url(&self, hostname: &str) -> String {
|
|
||||||
format!(
|
|
||||||
"{}://{}/u/{}",
|
|
||||||
Settings::get().get_protocol_string(),
|
|
||||||
hostname,
|
|
||||||
self.name
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn mark_as_updated(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set((last_refreshed_at.eq(naive_now()),))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn delete_account(conn: &PgConnection, user_id: i32) -> Result<User_, Error> {
|
|
||||||
diesel::update(user_.find(user_id))
|
|
||||||
.set((
|
|
||||||
preferred_username.eq::<Option<String>>(None),
|
|
||||||
email.eq::<Option<String>>(None),
|
|
||||||
matrix_user_id.eq::<Option<String>>(None),
|
|
||||||
bio.eq::<Option<String>>(None),
|
|
||||||
deleted.eq(true),
|
|
||||||
updated.eq(naive_now()),
|
|
||||||
))
|
|
||||||
.get_result::<Self>(conn)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use crate::{establish_unpooled_connection, source::user::*, ListingType, SortType};
|
|
||||||
use serial_test::serial;
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[serial]
|
|
||||||
fn test_crud() {
|
|
||||||
let conn = establish_unpooled_connection();
|
|
||||||
|
|
||||||
let new_user = UserForm {
|
|
||||||
name: "thommy".into(),
|
|
||||||
preferred_username: None,
|
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
|
||||||
banner: None,
|
|
||||||
admin: false,
|
|
||||||
banned: Some(false),
|
|
||||||
published: None,
|
|
||||||
updated: None,
|
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: None,
|
|
||||||
bio: None,
|
|
||||||
local: true,
|
|
||||||
private_key: None,
|
|
||||||
public_key: None,
|
|
||||||
last_refreshed_at: None,
|
|
||||||
inbox_url: None,
|
|
||||||
shared_inbox_url: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let inserted_user = User_::create(&conn, &new_user).unwrap();
|
|
||||||
|
|
||||||
let expected_user = User_ {
|
|
||||||
id: inserted_user.id,
|
|
||||||
name: "thommy".into(),
|
|
||||||
preferred_username: None,
|
|
||||||
password_encrypted: "nope".into(),
|
|
||||||
email: None,
|
|
||||||
matrix_user_id: None,
|
|
||||||
avatar: None,
|
|
||||||
banner: None,
|
|
||||||
admin: false,
|
|
||||||
banned: false,
|
|
||||||
published: inserted_user.published,
|
|
||||||
updated: None,
|
|
||||||
show_nsfw: false,
|
|
||||||
theme: "browser".into(),
|
|
||||||
default_sort_type: SortType::Hot as i16,
|
|
||||||
default_listing_type: ListingType::Subscribed as i16,
|
|
||||||
lang: "browser".into(),
|
|
||||||
show_avatars: true,
|
|
||||||
send_notifications_to_email: false,
|
|
||||||
actor_id: inserted_user.actor_id.to_owned(),
|
|
||||||
bio: None,
|
|
||||||
local: true,
|
|
||||||
private_key: None,
|
|
||||||
public_key: None,
|
|
||||||
last_refreshed_at: inserted_user.published,
|
|
||||||
deleted: false,
|
|
||||||
inbox_url: inserted_user.inbox_url.to_owned(),
|
|
||||||
shared_inbox_url: None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let read_user = User_::read(&conn, inserted_user.id).unwrap();
|
|
||||||
let updated_user = User_::update(&conn, inserted_user.id, &new_user).unwrap();
|
|
||||||
let num_deleted = User_::delete(&conn, inserted_user.id).unwrap();
|
|
||||||
|
|
||||||
assert_eq!(expected_user, read_user);
|
|
||||||
assert_eq!(expected_user, inserted_user);
|
|
||||||
assert_eq!(expected_user, updated_user);
|
|
||||||
assert_eq!(1, num_deleted);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -12,4 +12,5 @@ chrono = { version = "0.4.19", features = ["serde"] }
|
||||||
serde = { version = "1.0.123", features = ["derive"] }
|
serde = { version = "1.0.123", features = ["derive"] }
|
||||||
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
serde_json = { version = "1.0.61", features = ["preserve_order"] }
|
||||||
log = "0.4.14"
|
log = "0.4.14"
|
||||||
url = { version = "2.2.0", features = ["serde"] }
|
url = { version = "2.2.1", features = ["serde"] }
|
||||||
|
diesel-derive-newtype = "0.1"
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate diesel;
|
extern crate diesel;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
extern crate diesel_derive_newtype;
|
||||||
|
|
||||||
use chrono::NaiveDateTime;
|
use chrono::NaiveDateTime;
|
||||||
use diesel::{
|
use diesel::{
|
||||||
backend::Backend,
|
backend::Backend,
|
||||||
|
@ -8,21 +11,62 @@ use diesel::{
|
||||||
serialize::{Output, ToSql},
|
serialize::{Output, ToSql},
|
||||||
sql_types::Text,
|
sql_types::Text,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
|
fmt,
|
||||||
fmt::{Display, Formatter},
|
fmt::{Display, Formatter},
|
||||||
io::Write,
|
io::Write,
|
||||||
};
|
};
|
||||||
|
use url::Url;
|
||||||
|
|
||||||
pub mod schema;
|
pub mod schema;
|
||||||
pub mod source;
|
pub mod source;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
#[derive(Clone, PartialEq, Serialize, Debug, AsExpression, FromSqlRow)]
|
pub struct PostId(pub i32);
|
||||||
#[sql_type = "Text"]
|
|
||||||
pub struct Url(url::Url);
|
|
||||||
|
|
||||||
impl<DB: Backend> ToSql<Text, DB> for Url
|
impl fmt::Display for PostId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct PersonId(pub i32);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct CommentId(pub i32);
|
||||||
|
|
||||||
|
impl fmt::Display for CommentId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct CommunityId(pub i32);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct LocalUserId(pub i32);
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct PrivateMessageId(i32);
|
||||||
|
|
||||||
|
impl fmt::Display for PrivateMessageId {
|
||||||
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
|
write!(f, "{}", self.0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Copy, Clone, Hash, Eq, PartialEq, Serialize, Deserialize, DieselNewType)]
|
||||||
|
pub struct PersonMentionId(i32);
|
||||||
|
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(Clone, PartialEq, Serialize, Deserialize, Debug, AsExpression, FromSqlRow)]
|
||||||
|
#[sql_type = "Text"]
|
||||||
|
pub struct DbUrl(Url);
|
||||||
|
|
||||||
|
impl<DB: Backend> ToSql<Text, DB> for DbUrl
|
||||||
where
|
where
|
||||||
String: ToSql<Text, DB>,
|
String: ToSql<Text, DB>,
|
||||||
{
|
{
|
||||||
|
@ -31,37 +75,37 @@ where
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<DB: Backend> FromSql<Text, DB> for Url
|
impl<DB: Backend> FromSql<Text, DB> for DbUrl
|
||||||
where
|
where
|
||||||
String: FromSql<Text, DB>,
|
String: FromSql<Text, DB>,
|
||||||
{
|
{
|
||||||
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
fn from_sql(bytes: Option<&DB::RawValue>) -> diesel::deserialize::Result<Self> {
|
||||||
let str = String::from_sql(bytes)?;
|
let str = String::from_sql(bytes)?;
|
||||||
Ok(Url(url::Url::parse(&str)?))
|
Ok(DbUrl(Url::parse(&str)?))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Url {
|
impl DbUrl {
|
||||||
pub fn into_inner(self) -> url::Url {
|
pub fn into_inner(self) -> Url {
|
||||||
self.0
|
self.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Url {
|
impl Display for DbUrl {
|
||||||
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
||||||
self.to_owned().into_inner().fmt(f)
|
self.to_owned().into_inner().fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<Url> for url::Url {
|
impl From<DbUrl> for Url {
|
||||||
fn from(url: Url) -> Self {
|
fn from(url: DbUrl) -> Self {
|
||||||
url.0
|
url.0
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<url::Url> for Url {
|
impl From<Url> for DbUrl {
|
||||||
fn from(url: url::Url) -> Self {
|
fn from(url: Url) -> Self {
|
||||||
Url(url)
|
DbUrl(url)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
comment_like (id) {
|
comment_like (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
comment_id -> Int4,
|
comment_id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
score -> Int2,
|
score -> Int2,
|
||||||
|
@ -67,7 +67,7 @@ table! {
|
||||||
comment_saved (id) {
|
comment_saved (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
comment_id -> Int4,
|
comment_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -89,11 +89,11 @@ table! {
|
||||||
private_key -> Nullable<Text>,
|
private_key -> Nullable<Text>,
|
||||||
public_key -> Nullable<Text>,
|
public_key -> Nullable<Text>,
|
||||||
last_refreshed_at -> Timestamp,
|
last_refreshed_at -> Timestamp,
|
||||||
icon -> Nullable<Text>,
|
icon -> Nullable<Varchar>,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Varchar>,
|
||||||
followers_url -> Text,
|
followers_url -> Varchar,
|
||||||
inbox_url -> Text,
|
inbox_url -> Varchar,
|
||||||
shared_inbox_url -> Nullable<Text>,
|
shared_inbox_url -> Nullable<Varchar>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,7 +116,7 @@ table! {
|
||||||
community_follower (id) {
|
community_follower (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
pending -> Nullable<Bool>,
|
pending -> Nullable<Bool>,
|
||||||
}
|
}
|
||||||
|
@ -126,25 +126,44 @@ table! {
|
||||||
community_moderator (id) {
|
community_moderator (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
community_user_ban (id) {
|
community_person_ban (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
local_user (id) {
|
||||||
|
id -> Int4,
|
||||||
|
person_id -> Int4,
|
||||||
|
password_encrypted -> Text,
|
||||||
|
email -> Nullable<Text>,
|
||||||
|
admin -> Bool,
|
||||||
|
show_nsfw -> Bool,
|
||||||
|
theme -> Varchar,
|
||||||
|
default_sort_type -> Int2,
|
||||||
|
default_listing_type -> Int2,
|
||||||
|
lang -> Varchar,
|
||||||
|
show_avatars -> Bool,
|
||||||
|
send_notifications_to_email -> Bool,
|
||||||
|
matrix_user_id -> Nullable<Text>,
|
||||||
|
validator_time -> Timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
mod_add (id) {
|
mod_add (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
other_user_id -> Int4,
|
other_person_id -> Int4,
|
||||||
removed -> Nullable<Bool>,
|
removed -> Nullable<Bool>,
|
||||||
when_ -> Timestamp,
|
when_ -> Timestamp,
|
||||||
}
|
}
|
||||||
|
@ -153,8 +172,8 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_add_community (id) {
|
mod_add_community (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
other_user_id -> Int4,
|
other_person_id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
removed -> Nullable<Bool>,
|
removed -> Nullable<Bool>,
|
||||||
when_ -> Timestamp,
|
when_ -> Timestamp,
|
||||||
|
@ -164,8 +183,8 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_ban (id) {
|
mod_ban (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
other_user_id -> Int4,
|
other_person_id -> Int4,
|
||||||
reason -> Nullable<Text>,
|
reason -> Nullable<Text>,
|
||||||
banned -> Nullable<Bool>,
|
banned -> Nullable<Bool>,
|
||||||
expires -> Nullable<Timestamp>,
|
expires -> Nullable<Timestamp>,
|
||||||
|
@ -176,8 +195,8 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_ban_from_community (id) {
|
mod_ban_from_community (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
other_user_id -> Int4,
|
other_person_id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
reason -> Nullable<Text>,
|
reason -> Nullable<Text>,
|
||||||
banned -> Nullable<Bool>,
|
banned -> Nullable<Bool>,
|
||||||
|
@ -189,7 +208,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_lock_post (id) {
|
mod_lock_post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
locked -> Nullable<Bool>,
|
locked -> Nullable<Bool>,
|
||||||
when_ -> Timestamp,
|
when_ -> Timestamp,
|
||||||
|
@ -199,7 +218,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_remove_comment (id) {
|
mod_remove_comment (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
comment_id -> Int4,
|
comment_id -> Int4,
|
||||||
reason -> Nullable<Text>,
|
reason -> Nullable<Text>,
|
||||||
removed -> Nullable<Bool>,
|
removed -> Nullable<Bool>,
|
||||||
|
@ -210,7 +229,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_remove_community (id) {
|
mod_remove_community (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
reason -> Nullable<Text>,
|
reason -> Nullable<Text>,
|
||||||
removed -> Nullable<Bool>,
|
removed -> Nullable<Bool>,
|
||||||
|
@ -222,7 +241,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_remove_post (id) {
|
mod_remove_post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
reason -> Nullable<Text>,
|
reason -> Nullable<Text>,
|
||||||
removed -> Nullable<Bool>,
|
removed -> Nullable<Bool>,
|
||||||
|
@ -233,7 +252,7 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
mod_sticky_post (id) {
|
mod_sticky_post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
mod_user_id -> Int4,
|
mod_person_id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
stickied -> Nullable<Bool>,
|
stickied -> Nullable<Bool>,
|
||||||
when_ -> Timestamp,
|
when_ -> Timestamp,
|
||||||
|
@ -243,9 +262,60 @@ table! {
|
||||||
table! {
|
table! {
|
||||||
password_reset_request (id) {
|
password_reset_request (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
user_id -> Int4,
|
|
||||||
token_encrypted -> Text,
|
token_encrypted -> Text,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
|
local_user_id -> Int4,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
person (id) {
|
||||||
|
id -> Int4,
|
||||||
|
name -> Varchar,
|
||||||
|
preferred_username -> Nullable<Varchar>,
|
||||||
|
avatar -> Nullable<Varchar>,
|
||||||
|
banned -> Bool,
|
||||||
|
published -> Timestamp,
|
||||||
|
updated -> Nullable<Timestamp>,
|
||||||
|
actor_id -> Varchar,
|
||||||
|
bio -> Nullable<Text>,
|
||||||
|
local -> Bool,
|
||||||
|
private_key -> Nullable<Text>,
|
||||||
|
public_key -> Nullable<Text>,
|
||||||
|
last_refreshed_at -> Timestamp,
|
||||||
|
banner -> Nullable<Varchar>,
|
||||||
|
deleted -> Bool,
|
||||||
|
inbox_url -> Varchar,
|
||||||
|
shared_inbox_url -> Nullable<Varchar>,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
person_aggregates (id) {
|
||||||
|
id -> Int4,
|
||||||
|
person_id -> Int4,
|
||||||
|
post_count -> Int8,
|
||||||
|
post_score -> Int8,
|
||||||
|
comment_count -> Int8,
|
||||||
|
comment_score -> Int8,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
person_ban (id) {
|
||||||
|
id -> Int4,
|
||||||
|
person_id -> Int4,
|
||||||
|
published -> Timestamp,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
table! {
|
||||||
|
person_mention (id) {
|
||||||
|
id -> Int4,
|
||||||
|
recipient_id -> Int4,
|
||||||
|
comment_id -> Int4,
|
||||||
|
read -> Bool,
|
||||||
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +323,7 @@ table! {
|
||||||
post (id) {
|
post (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
url -> Nullable<Text>,
|
url -> Nullable<Varchar>,
|
||||||
body -> Nullable<Text>,
|
body -> Nullable<Text>,
|
||||||
creator_id -> Int4,
|
creator_id -> Int4,
|
||||||
community_id -> Int4,
|
community_id -> Int4,
|
||||||
|
@ -292,7 +362,7 @@ table! {
|
||||||
post_like (id) {
|
post_like (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
score -> Int2,
|
score -> Int2,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
|
@ -302,7 +372,7 @@ table! {
|
||||||
post_read (id) {
|
post_read (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -327,7 +397,7 @@ table! {
|
||||||
post_saved (id) {
|
post_saved (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
post_id -> Int4,
|
post_id -> Int4,
|
||||||
user_id -> Int4,
|
person_id -> Int4,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -358,8 +428,8 @@ table! {
|
||||||
enable_downvotes -> Bool,
|
enable_downvotes -> Bool,
|
||||||
open_registration -> Bool,
|
open_registration -> Bool,
|
||||||
enable_nsfw -> Bool,
|
enable_nsfw -> Bool,
|
||||||
icon -> Nullable<Text>,
|
icon -> Nullable<Varchar>,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Varchar>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -378,68 +448,6 @@ table! {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
|
||||||
user_ (id) {
|
|
||||||
id -> Int4,
|
|
||||||
name -> Varchar,
|
|
||||||
preferred_username -> Nullable<Varchar>,
|
|
||||||
password_encrypted -> Text,
|
|
||||||
email -> Nullable<Text>,
|
|
||||||
avatar -> Nullable<Text>,
|
|
||||||
admin -> Bool,
|
|
||||||
banned -> Bool,
|
|
||||||
published -> Timestamp,
|
|
||||||
updated -> Nullable<Timestamp>,
|
|
||||||
show_nsfw -> Bool,
|
|
||||||
theme -> Varchar,
|
|
||||||
default_sort_type -> Int2,
|
|
||||||
default_listing_type -> Int2,
|
|
||||||
lang -> Varchar,
|
|
||||||
show_avatars -> Bool,
|
|
||||||
send_notifications_to_email -> Bool,
|
|
||||||
matrix_user_id -> Nullable<Text>,
|
|
||||||
actor_id -> Varchar,
|
|
||||||
bio -> Nullable<Text>,
|
|
||||||
local -> Bool,
|
|
||||||
private_key -> Nullable<Text>,
|
|
||||||
public_key -> Nullable<Text>,
|
|
||||||
last_refreshed_at -> Timestamp,
|
|
||||||
banner -> Nullable<Text>,
|
|
||||||
deleted -> Bool,
|
|
||||||
inbox_url -> Text,
|
|
||||||
shared_inbox_url -> Nullable<Text>,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
user_aggregates (id) {
|
|
||||||
id -> Int4,
|
|
||||||
user_id -> Int4,
|
|
||||||
post_count -> Int8,
|
|
||||||
post_score -> Int8,
|
|
||||||
comment_count -> Int8,
|
|
||||||
comment_score -> Int8,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
user_ban (id) {
|
|
||||||
id -> Int4,
|
|
||||||
user_id -> Int4,
|
|
||||||
published -> Timestamp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
table! {
|
|
||||||
user_mention (id) {
|
|
||||||
id -> Int4,
|
|
||||||
recipient_id -> Int4,
|
|
||||||
comment_id -> Int4,
|
|
||||||
read -> Bool,
|
|
||||||
published -> Timestamp,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// These are necessary since diesel doesn't have self joins / aliases
|
// These are necessary since diesel doesn't have self joins / aliases
|
||||||
table! {
|
table! {
|
||||||
comment_alias_1 (id) {
|
comment_alias_1 (id) {
|
||||||
|
@ -459,122 +467,105 @@ table! {
|
||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
user_alias_1 (id) {
|
person_alias_1 (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
preferred_username -> Nullable<Varchar>,
|
preferred_username -> Nullable<Varchar>,
|
||||||
password_encrypted -> Text,
|
avatar -> Nullable<Varchar>,
|
||||||
email -> Nullable<Text>,
|
|
||||||
avatar -> Nullable<Text>,
|
|
||||||
admin -> Bool,
|
|
||||||
banned -> Bool,
|
banned -> Bool,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
updated -> Nullable<Timestamp>,
|
updated -> Nullable<Timestamp>,
|
||||||
show_nsfw -> Bool,
|
|
||||||
theme -> Varchar,
|
|
||||||
default_sort_type -> Int2,
|
|
||||||
default_listing_type -> Int2,
|
|
||||||
lang -> Varchar,
|
|
||||||
show_avatars -> Bool,
|
|
||||||
send_notifications_to_email -> Bool,
|
|
||||||
matrix_user_id -> Nullable<Text>,
|
|
||||||
actor_id -> Varchar,
|
actor_id -> Varchar,
|
||||||
bio -> Nullable<Text>,
|
bio -> Nullable<Text>,
|
||||||
local -> Bool,
|
local -> Bool,
|
||||||
private_key -> Nullable<Text>,
|
private_key -> Nullable<Text>,
|
||||||
public_key -> Nullable<Text>,
|
public_key -> Nullable<Text>,
|
||||||
last_refreshed_at -> Timestamp,
|
last_refreshed_at -> Timestamp,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Varchar>,
|
||||||
deleted -> Bool,
|
deleted -> Bool,
|
||||||
|
inbox_url -> Varchar,
|
||||||
|
shared_inbox_url -> Nullable<Varchar>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
table! {
|
table! {
|
||||||
user_alias_2 (id) {
|
person_alias_2 (id) {
|
||||||
id -> Int4,
|
id -> Int4,
|
||||||
name -> Varchar,
|
name -> Varchar,
|
||||||
preferred_username -> Nullable<Varchar>,
|
preferred_username -> Nullable<Varchar>,
|
||||||
password_encrypted -> Text,
|
avatar -> Nullable<Varchar>,
|
||||||
email -> Nullable<Text>,
|
|
||||||
avatar -> Nullable<Text>,
|
|
||||||
admin -> Bool,
|
|
||||||
banned -> Bool,
|
banned -> Bool,
|
||||||
published -> Timestamp,
|
published -> Timestamp,
|
||||||
updated -> Nullable<Timestamp>,
|
updated -> Nullable<Timestamp>,
|
||||||
show_nsfw -> Bool,
|
|
||||||
theme -> Varchar,
|
|
||||||
default_sort_type -> Int2,
|
|
||||||
default_listing_type -> Int2,
|
|
||||||
lang -> Varchar,
|
|
||||||
show_avatars -> Bool,
|
|
||||||
send_notifications_to_email -> Bool,
|
|
||||||
matrix_user_id -> Nullable<Text>,
|
|
||||||
actor_id -> Varchar,
|
actor_id -> Varchar,
|
||||||
bio -> Nullable<Text>,
|
bio -> Nullable<Text>,
|
||||||
local -> Bool,
|
local -> Bool,
|
||||||
private_key -> Nullable<Text>,
|
private_key -> Nullable<Text>,
|
||||||
public_key -> Nullable<Text>,
|
public_key -> Nullable<Text>,
|
||||||
last_refreshed_at -> Timestamp,
|
last_refreshed_at -> Timestamp,
|
||||||
banner -> Nullable<Text>,
|
banner -> Nullable<Varchar>,
|
||||||
deleted -> Bool,
|
deleted -> Bool,
|
||||||
|
inbox_url -> Varchar,
|
||||||
|
shared_inbox_url -> Nullable<Varchar>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
joinable!(comment_alias_1 -> user_alias_1 (creator_id));
|
joinable!(comment_alias_1 -> person_alias_1 (creator_id));
|
||||||
joinable!(comment -> comment_alias_1 (parent_id));
|
joinable!(comment -> comment_alias_1 (parent_id));
|
||||||
joinable!(user_mention -> user_alias_1 (recipient_id));
|
joinable!(person_mention -> person_alias_1 (recipient_id));
|
||||||
joinable!(post -> user_alias_1 (creator_id));
|
joinable!(post -> person_alias_1 (creator_id));
|
||||||
joinable!(comment -> user_alias_1 (creator_id));
|
joinable!(comment -> person_alias_1 (creator_id));
|
||||||
|
|
||||||
joinable!(post_report -> user_alias_2 (resolver_id));
|
joinable!(post_report -> person_alias_2 (resolver_id));
|
||||||
joinable!(comment_report -> user_alias_2 (resolver_id));
|
joinable!(comment_report -> person_alias_2 (resolver_id));
|
||||||
|
|
||||||
|
joinable!(comment -> person (creator_id));
|
||||||
joinable!(comment -> post (post_id));
|
joinable!(comment -> post (post_id));
|
||||||
joinable!(comment -> user_ (creator_id));
|
|
||||||
joinable!(comment_aggregates -> comment (comment_id));
|
joinable!(comment_aggregates -> comment (comment_id));
|
||||||
joinable!(comment_like -> comment (comment_id));
|
joinable!(comment_like -> comment (comment_id));
|
||||||
|
joinable!(comment_like -> person (person_id));
|
||||||
joinable!(comment_like -> post (post_id));
|
joinable!(comment_like -> post (post_id));
|
||||||
joinable!(comment_like -> user_ (user_id));
|
|
||||||
joinable!(comment_report -> comment (comment_id));
|
joinable!(comment_report -> comment (comment_id));
|
||||||
joinable!(comment_saved -> comment (comment_id));
|
joinable!(comment_saved -> comment (comment_id));
|
||||||
joinable!(comment_saved -> user_ (user_id));
|
joinable!(comment_saved -> person (person_id));
|
||||||
joinable!(community -> user_ (creator_id));
|
joinable!(community -> person (creator_id));
|
||||||
joinable!(community_aggregates -> community (community_id));
|
joinable!(community_aggregates -> community (community_id));
|
||||||
joinable!(community_follower -> community (community_id));
|
joinable!(community_follower -> community (community_id));
|
||||||
joinable!(community_follower -> user_ (user_id));
|
joinable!(community_follower -> person (person_id));
|
||||||
joinable!(community_moderator -> community (community_id));
|
joinable!(community_moderator -> community (community_id));
|
||||||
joinable!(community_moderator -> user_ (user_id));
|
joinable!(community_moderator -> person (person_id));
|
||||||
joinable!(community_user_ban -> community (community_id));
|
joinable!(community_person_ban -> community (community_id));
|
||||||
joinable!(community_user_ban -> user_ (user_id));
|
joinable!(community_person_ban -> person (person_id));
|
||||||
|
joinable!(local_user -> person (person_id));
|
||||||
joinable!(mod_add_community -> community (community_id));
|
joinable!(mod_add_community -> community (community_id));
|
||||||
joinable!(mod_ban_from_community -> community (community_id));
|
joinable!(mod_ban_from_community -> community (community_id));
|
||||||
|
joinable!(mod_lock_post -> person (mod_person_id));
|
||||||
joinable!(mod_lock_post -> post (post_id));
|
joinable!(mod_lock_post -> post (post_id));
|
||||||
joinable!(mod_lock_post -> user_ (mod_user_id));
|
|
||||||
joinable!(mod_remove_comment -> comment (comment_id));
|
joinable!(mod_remove_comment -> comment (comment_id));
|
||||||
joinable!(mod_remove_comment -> user_ (mod_user_id));
|
joinable!(mod_remove_comment -> person (mod_person_id));
|
||||||
joinable!(mod_remove_community -> community (community_id));
|
joinable!(mod_remove_community -> community (community_id));
|
||||||
joinable!(mod_remove_community -> user_ (mod_user_id));
|
joinable!(mod_remove_community -> person (mod_person_id));
|
||||||
|
joinable!(mod_remove_post -> person (mod_person_id));
|
||||||
joinable!(mod_remove_post -> post (post_id));
|
joinable!(mod_remove_post -> post (post_id));
|
||||||
joinable!(mod_remove_post -> user_ (mod_user_id));
|
joinable!(mod_sticky_post -> person (mod_person_id));
|
||||||
joinable!(mod_sticky_post -> post (post_id));
|
joinable!(mod_sticky_post -> post (post_id));
|
||||||
joinable!(mod_sticky_post -> user_ (mod_user_id));
|
joinable!(password_reset_request -> local_user (local_user_id));
|
||||||
joinable!(password_reset_request -> user_ (user_id));
|
joinable!(person_aggregates -> person (person_id));
|
||||||
|
joinable!(person_ban -> person (person_id));
|
||||||
|
joinable!(person_mention -> comment (comment_id));
|
||||||
|
joinable!(person_mention -> person (recipient_id));
|
||||||
joinable!(post -> community (community_id));
|
joinable!(post -> community (community_id));
|
||||||
joinable!(post -> user_ (creator_id));
|
joinable!(post -> person (creator_id));
|
||||||
joinable!(post_aggregates -> post (post_id));
|
joinable!(post_aggregates -> post (post_id));
|
||||||
|
joinable!(post_like -> person (person_id));
|
||||||
joinable!(post_like -> post (post_id));
|
joinable!(post_like -> post (post_id));
|
||||||
joinable!(post_like -> user_ (user_id));
|
joinable!(post_read -> person (person_id));
|
||||||
joinable!(post_read -> post (post_id));
|
joinable!(post_read -> post (post_id));
|
||||||
joinable!(post_read -> user_ (user_id));
|
|
||||||
joinable!(post_report -> post (post_id));
|
joinable!(post_report -> post (post_id));
|
||||||
|
joinable!(post_saved -> person (person_id));
|
||||||
joinable!(post_saved -> post (post_id));
|
joinable!(post_saved -> post (post_id));
|
||||||
joinable!(post_saved -> user_ (user_id));
|
joinable!(site -> person (creator_id));
|
||||||
joinable!(site -> user_ (creator_id));
|
|
||||||
joinable!(site_aggregates -> site (site_id));
|
joinable!(site_aggregates -> site (site_id));
|
||||||
joinable!(user_aggregates -> user_ (user_id));
|
|
||||||
joinable!(user_ban -> user_ (user_id));
|
|
||||||
joinable!(user_mention -> comment (comment_id));
|
|
||||||
joinable!(user_mention -> user_ (recipient_id));
|
|
||||||
|
|
||||||
allow_tables_to_appear_in_same_query!(
|
allow_tables_to_appear_in_same_query!(
|
||||||
activity,
|
activity,
|
||||||
|
@ -587,7 +578,8 @@ allow_tables_to_appear_in_same_query!(
|
||||||
community_aggregates,
|
community_aggregates,
|
||||||
community_follower,
|
community_follower,
|
||||||
community_moderator,
|
community_moderator,
|
||||||
community_user_ban,
|
community_person_ban,
|
||||||
|
local_user,
|
||||||
mod_add,
|
mod_add,
|
||||||
mod_add_community,
|
mod_add_community,
|
||||||
mod_ban,
|
mod_ban,
|
||||||
|
@ -598,6 +590,10 @@ allow_tables_to_appear_in_same_query!(
|
||||||
mod_remove_post,
|
mod_remove_post,
|
||||||
mod_sticky_post,
|
mod_sticky_post,
|
||||||
password_reset_request,
|
password_reset_request,
|
||||||
|
person,
|
||||||
|
person_aggregates,
|
||||||
|
person_ban,
|
||||||
|
person_mention,
|
||||||
post,
|
post,
|
||||||
post_aggregates,
|
post_aggregates,
|
||||||
post_like,
|
post_like,
|
||||||
|
@ -607,11 +603,7 @@ allow_tables_to_appear_in_same_query!(
|
||||||
private_message,
|
private_message,
|
||||||
site,
|
site,
|
||||||
site_aggregates,
|
site_aggregates,
|
||||||
user_,
|
|
||||||
user_aggregates,
|
|
||||||
user_ban,
|
|
||||||
user_mention,
|
|
||||||
comment_alias_1,
|
comment_alias_1,
|
||||||
user_alias_1,
|
person_alias_1,
|
||||||
user_alias_2,
|
person_alias_2,
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::schema::activity;
|
use crate::{schema::activity, DbUrl};
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ pub struct Activity {
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: Option<String>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub sensitive: Option<bool>,
|
pub sensitive: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,6 @@ pub struct ActivityForm {
|
||||||
pub data: Value,
|
pub data: Value,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub ap_id: String,
|
pub ap_id: DbUrl,
|
||||||
pub sensitive: bool,
|
pub sensitive: bool,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{comment, comment_alias_1, comment_like, comment_saved},
|
schema::{comment, comment_alias_1, comment_like, comment_saved},
|
||||||
source::post::Post,
|
source::post::Post,
|
||||||
Url,
|
CommentId,
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
|
PostId,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -16,17 +19,17 @@ use serde::Serialize;
|
||||||
#[belongs_to(Post)]
|
#[belongs_to(Post)]
|
||||||
#[table_name = "comment"]
|
#[table_name = "comment"]
|
||||||
pub struct Comment {
|
pub struct Comment {
|
||||||
pub id: i32,
|
pub id: CommentId,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub parent_id: Option<i32>,
|
pub parent_id: Option<CommentId>,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub read: bool, // Whether the recipient has read the comment or not
|
pub read: bool, // Whether the recipient has read the comment or not
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,33 +37,33 @@ pub struct Comment {
|
||||||
#[belongs_to(Post)]
|
#[belongs_to(Post)]
|
||||||
#[table_name = "comment_alias_1"]
|
#[table_name = "comment_alias_1"]
|
||||||
pub struct CommentAlias1 {
|
pub struct CommentAlias1 {
|
||||||
pub id: i32,
|
pub id: CommentId,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub parent_id: Option<i32>,
|
pub parent_id: Option<CommentId>,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub read: bool, // Whether the recipient has read the comment or not
|
pub read: bool, // Whether the recipient has read the comment or not
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub ap_id: Url,
|
pub ap_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "comment"]
|
#[table_name = "comment"]
|
||||||
pub struct CommentForm {
|
pub struct CommentForm {
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub parent_id: Option<i32>,
|
pub parent_id: Option<CommentId>,
|
||||||
pub content: String,
|
pub content: String,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub read: Option<bool>,
|
pub read: Option<bool>,
|
||||||
pub published: Option<chrono::NaiveDateTime>,
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub ap_id: Option<Url>,
|
pub ap_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,9 +72,9 @@ pub struct CommentForm {
|
||||||
#[table_name = "comment_like"]
|
#[table_name = "comment_like"]
|
||||||
pub struct CommentLike {
|
pub struct CommentLike {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub post_id: i32, // TODO this is redundant
|
pub post_id: PostId, // TODO this is redundant
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
@ -79,9 +82,9 @@ pub struct CommentLike {
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "comment_like"]
|
#[table_name = "comment_like"]
|
||||||
pub struct CommentLikeForm {
|
pub struct CommentLikeForm {
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub post_id: i32, // TODO this is redundant
|
pub post_id: PostId, // TODO this is redundant
|
||||||
pub score: i16,
|
pub score: i16,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,14 +93,14 @@ pub struct CommentLikeForm {
|
||||||
#[table_name = "comment_saved"]
|
#[table_name = "comment_saved"]
|
||||||
pub struct CommentSaved {
|
pub struct CommentSaved {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "comment_saved"]
|
#[table_name = "comment_saved"]
|
||||||
pub struct CommentSavedForm {
|
pub struct CommentSavedForm {
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::{schema::comment_report, source::comment::Comment};
|
use crate::{schema::comment_report, source::comment::Comment, CommentId, PersonId};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
#[derive(
|
#[derive(
|
||||||
|
@ -8,12 +8,12 @@ use serde::{Deserialize, Serialize};
|
||||||
#[table_name = "comment_report"]
|
#[table_name = "comment_report"]
|
||||||
pub struct CommentReport {
|
pub struct CommentReport {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub original_comment_text: String,
|
pub original_comment_text: String,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
pub resolved: bool,
|
pub resolved: bool,
|
||||||
pub resolver_id: Option<i32>,
|
pub resolver_id: Option<PersonId>,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@ pub struct CommentReport {
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "comment_report"]
|
#[table_name = "comment_report"]
|
||||||
pub struct CommentReportForm {
|
pub struct CommentReportForm {
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub original_comment_text: String,
|
pub original_comment_text: String,
|
||||||
pub reason: String,
|
pub reason: String,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +1,54 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
schema::{community, community_follower, community_moderator, community_user_ban},
|
schema::{community, community_follower, community_moderator, community_person_ban},
|
||||||
Url,
|
CommunityId,
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
#[table_name = "community"]
|
#[table_name = "community"]
|
||||||
pub struct Community {
|
pub struct Community {
|
||||||
pub id: i32,
|
pub id: CommunityId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: chrono::NaiveDateTime,
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<DbUrl>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
pub followers_url: Url,
|
pub followers_url: DbUrl,
|
||||||
pub inbox_url: Url,
|
pub inbox_url: DbUrl,
|
||||||
pub shared_inbox_url: Option<Url>,
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A safe representation of community, without the sensitive info
|
/// A safe representation of community, without the sensitive info
|
||||||
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
#[table_name = "community"]
|
#[table_name = "community"]
|
||||||
pub struct CommunitySafe {
|
pub struct CommunitySafe {
|
||||||
pub id: i32,
|
pub id: CommunityId,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub removed: bool,
|
pub removed: bool,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: bool,
|
pub deleted: bool,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Url,
|
pub actor_id: DbUrl,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub icon: Option<String>,
|
pub icon: Option<DbUrl>,
|
||||||
pub banner: Option<String>,
|
pub banner: Option<DbUrl>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Debug)]
|
#[derive(Insertable, AsChangeset, Debug)]
|
||||||
|
@ -55,22 +57,22 @@ pub struct CommunityForm {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub title: String,
|
pub title: String,
|
||||||
pub description: Option<String>,
|
pub description: Option<String>,
|
||||||
pub creator_id: i32,
|
pub creator_id: PersonId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub published: Option<chrono::NaiveDateTime>,
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
pub updated: Option<chrono::NaiveDateTime>,
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
pub deleted: Option<bool>,
|
pub deleted: Option<bool>,
|
||||||
pub nsfw: bool,
|
pub nsfw: bool,
|
||||||
pub actor_id: Option<Url>,
|
pub actor_id: Option<DbUrl>,
|
||||||
pub local: bool,
|
pub local: bool,
|
||||||
pub private_key: Option<String>,
|
pub private_key: Option<String>,
|
||||||
pub public_key: Option<String>,
|
pub public_key: Option<String>,
|
||||||
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||||
pub icon: Option<Option<String>>,
|
pub icon: Option<Option<DbUrl>>,
|
||||||
pub banner: Option<Option<String>>,
|
pub banner: Option<Option<DbUrl>>,
|
||||||
pub followers_url: Option<Url>,
|
pub followers_url: Option<DbUrl>,
|
||||||
pub inbox_url: Option<Url>,
|
pub inbox_url: Option<DbUrl>,
|
||||||
pub shared_inbox_url: Option<Option<Url>>,
|
pub shared_inbox_url: Option<Option<DbUrl>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||||
|
@ -78,33 +80,33 @@ pub struct CommunityForm {
|
||||||
#[table_name = "community_moderator"]
|
#[table_name = "community_moderator"]
|
||||||
pub struct CommunityModerator {
|
pub struct CommunityModerator {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "community_moderator"]
|
#[table_name = "community_moderator"]
|
||||||
pub struct CommunityModeratorForm {
|
pub struct CommunityModeratorForm {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||||
#[belongs_to(Community)]
|
#[belongs_to(Community)]
|
||||||
#[table_name = "community_user_ban"]
|
#[table_name = "community_person_ban"]
|
||||||
pub struct CommunityUserBan {
|
pub struct CommunityPersonBan {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "community_user_ban"]
|
#[table_name = "community_person_ban"]
|
||||||
pub struct CommunityUserBanForm {
|
pub struct CommunityPersonBanForm {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
#[derive(Identifiable, Queryable, Associations, PartialEq, Debug)]
|
||||||
|
@ -112,8 +114,8 @@ pub struct CommunityUserBanForm {
|
||||||
#[table_name = "community_follower"]
|
#[table_name = "community_follower"]
|
||||||
pub struct CommunityFollower {
|
pub struct CommunityFollower {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
pub pending: Option<bool>,
|
pub pending: Option<bool>,
|
||||||
}
|
}
|
||||||
|
@ -121,7 +123,7 @@ pub struct CommunityFollower {
|
||||||
#[derive(Insertable, AsChangeset, Clone)]
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
#[table_name = "community_follower"]
|
#[table_name = "community_follower"]
|
||||||
pub struct CommunityFollowerForm {
|
pub struct CommunityFollowerForm {
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub user_id: i32,
|
pub person_id: PersonId,
|
||||||
pub pending: bool,
|
pub pending: bool,
|
||||||
}
|
}
|
||||||
|
|
58
crates/db_schema/src/source/local_user.rs
Normal file
58
crates/db_schema/src/source/local_user.rs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
use crate::{schema::local_user, LocalUserId, PersonId};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "local_user"]
|
||||||
|
pub struct LocalUser {
|
||||||
|
pub id: LocalUserId,
|
||||||
|
pub person_id: PersonId,
|
||||||
|
pub password_encrypted: String,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub admin: bool,
|
||||||
|
pub show_nsfw: bool,
|
||||||
|
pub theme: String,
|
||||||
|
pub default_sort_type: i16,
|
||||||
|
pub default_listing_type: i16,
|
||||||
|
pub lang: String,
|
||||||
|
pub show_avatars: bool,
|
||||||
|
pub send_notifications_to_email: bool,
|
||||||
|
pub matrix_user_id: Option<String>,
|
||||||
|
pub validator_time: chrono::NaiveDateTime,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO redo these, check table defaults
|
||||||
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
|
#[table_name = "local_user"]
|
||||||
|
pub struct LocalUserForm {
|
||||||
|
pub person_id: PersonId,
|
||||||
|
pub password_encrypted: String,
|
||||||
|
pub email: Option<Option<String>>,
|
||||||
|
pub admin: Option<bool>,
|
||||||
|
pub show_nsfw: Option<bool>,
|
||||||
|
pub theme: Option<String>,
|
||||||
|
pub default_sort_type: Option<i16>,
|
||||||
|
pub default_listing_type: Option<i16>,
|
||||||
|
pub lang: Option<String>,
|
||||||
|
pub show_avatars: Option<bool>,
|
||||||
|
pub send_notifications_to_email: Option<bool>,
|
||||||
|
pub matrix_user_id: Option<Option<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A local user view that removes password encrypted
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "local_user"]
|
||||||
|
pub struct LocalUserSettings {
|
||||||
|
pub id: LocalUserId,
|
||||||
|
pub person_id: PersonId,
|
||||||
|
pub email: Option<String>,
|
||||||
|
pub admin: bool,
|
||||||
|
pub show_nsfw: bool,
|
||||||
|
pub theme: String,
|
||||||
|
pub default_sort_type: i16,
|
||||||
|
pub default_listing_type: i16,
|
||||||
|
pub lang: String,
|
||||||
|
pub show_avatars: bool,
|
||||||
|
pub send_notifications_to_email: bool,
|
||||||
|
pub matrix_user_id: Option<String>,
|
||||||
|
pub validator_time: chrono::NaiveDateTime,
|
||||||
|
}
|
|
@ -2,11 +2,12 @@ pub mod activity;
|
||||||
pub mod comment;
|
pub mod comment;
|
||||||
pub mod comment_report;
|
pub mod comment_report;
|
||||||
pub mod community;
|
pub mod community;
|
||||||
|
pub mod local_user;
|
||||||
pub mod moderator;
|
pub mod moderator;
|
||||||
pub mod password_reset_request;
|
pub mod password_reset_request;
|
||||||
|
pub mod person;
|
||||||
|
pub mod person_mention;
|
||||||
pub mod post;
|
pub mod post;
|
||||||
pub mod post_report;
|
pub mod post_report;
|
||||||
pub mod private_message;
|
pub mod private_message;
|
||||||
pub mod site;
|
pub mod site;
|
||||||
pub mod user;
|
|
||||||
pub mod user_mention;
|
|
||||||
|
|
|
@ -1,13 +1,19 @@
|
||||||
use crate::schema::{
|
use crate::{
|
||||||
mod_add,
|
schema::{
|
||||||
mod_add_community,
|
mod_add,
|
||||||
mod_ban,
|
mod_add_community,
|
||||||
mod_ban_from_community,
|
mod_ban,
|
||||||
mod_lock_post,
|
mod_ban_from_community,
|
||||||
mod_remove_comment,
|
mod_lock_post,
|
||||||
mod_remove_community,
|
mod_remove_comment,
|
||||||
mod_remove_post,
|
mod_remove_community,
|
||||||
mod_sticky_post,
|
mod_remove_post,
|
||||||
|
mod_sticky_post,
|
||||||
|
},
|
||||||
|
CommentId,
|
||||||
|
CommunityId,
|
||||||
|
PersonId,
|
||||||
|
PostId,
|
||||||
};
|
};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
|
@ -15,8 +21,8 @@ use serde::Serialize;
|
||||||
#[table_name = "mod_remove_post"]
|
#[table_name = "mod_remove_post"]
|
||||||
pub struct ModRemovePost {
|
pub struct ModRemovePost {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
|
@ -25,8 +31,8 @@ pub struct ModRemovePost {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_remove_post"]
|
#[table_name = "mod_remove_post"]
|
||||||
pub struct ModRemovePostForm {
|
pub struct ModRemovePostForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
@ -35,8 +41,8 @@ pub struct ModRemovePostForm {
|
||||||
#[table_name = "mod_lock_post"]
|
#[table_name = "mod_lock_post"]
|
||||||
pub struct ModLockPost {
|
pub struct ModLockPost {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub locked: Option<bool>,
|
pub locked: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
@ -44,8 +50,8 @@ pub struct ModLockPost {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_lock_post"]
|
#[table_name = "mod_lock_post"]
|
||||||
pub struct ModLockPostForm {
|
pub struct ModLockPostForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub locked: Option<bool>,
|
pub locked: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,8 +59,8 @@ pub struct ModLockPostForm {
|
||||||
#[table_name = "mod_sticky_post"]
|
#[table_name = "mod_sticky_post"]
|
||||||
pub struct ModStickyPost {
|
pub struct ModStickyPost {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub stickied: Option<bool>,
|
pub stickied: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
@ -62,8 +68,8 @@ pub struct ModStickyPost {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_sticky_post"]
|
#[table_name = "mod_sticky_post"]
|
||||||
pub struct ModStickyPostForm {
|
pub struct ModStickyPostForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub post_id: i32,
|
pub post_id: PostId,
|
||||||
pub stickied: Option<bool>,
|
pub stickied: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,8 +77,8 @@ pub struct ModStickyPostForm {
|
||||||
#[table_name = "mod_remove_comment"]
|
#[table_name = "mod_remove_comment"]
|
||||||
pub struct ModRemoveComment {
|
pub struct ModRemoveComment {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
|
@ -81,8 +87,8 @@ pub struct ModRemoveComment {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_remove_comment"]
|
#[table_name = "mod_remove_comment"]
|
||||||
pub struct ModRemoveCommentForm {
|
pub struct ModRemoveCommentForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub comment_id: i32,
|
pub comment_id: CommentId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
@ -91,8 +97,8 @@ pub struct ModRemoveCommentForm {
|
||||||
#[table_name = "mod_remove_community"]
|
#[table_name = "mod_remove_community"]
|
||||||
pub struct ModRemoveCommunity {
|
pub struct ModRemoveCommunity {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -102,8 +108,8 @@ pub struct ModRemoveCommunity {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_remove_community"]
|
#[table_name = "mod_remove_community"]
|
||||||
pub struct ModRemoveCommunityForm {
|
pub struct ModRemoveCommunityForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -113,9 +119,9 @@ pub struct ModRemoveCommunityForm {
|
||||||
#[table_name = "mod_ban_from_community"]
|
#[table_name = "mod_ban_from_community"]
|
||||||
pub struct ModBanFromCommunity {
|
pub struct ModBanFromCommunity {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub banned: Option<bool>,
|
pub banned: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -125,9 +131,9 @@ pub struct ModBanFromCommunity {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_ban_from_community"]
|
#[table_name = "mod_ban_from_community"]
|
||||||
pub struct ModBanFromCommunityForm {
|
pub struct ModBanFromCommunityForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub banned: Option<bool>,
|
pub banned: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -137,8 +143,8 @@ pub struct ModBanFromCommunityForm {
|
||||||
#[table_name = "mod_ban"]
|
#[table_name = "mod_ban"]
|
||||||
pub struct ModBan {
|
pub struct ModBan {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub banned: Option<bool>,
|
pub banned: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -148,8 +154,8 @@ pub struct ModBan {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_ban"]
|
#[table_name = "mod_ban"]
|
||||||
pub struct ModBanForm {
|
pub struct ModBanForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub reason: Option<String>,
|
pub reason: Option<String>,
|
||||||
pub banned: Option<bool>,
|
pub banned: Option<bool>,
|
||||||
pub expires: Option<chrono::NaiveDateTime>,
|
pub expires: Option<chrono::NaiveDateTime>,
|
||||||
|
@ -159,9 +165,9 @@ pub struct ModBanForm {
|
||||||
#[table_name = "mod_add_community"]
|
#[table_name = "mod_add_community"]
|
||||||
pub struct ModAddCommunity {
|
pub struct ModAddCommunity {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
@ -169,9 +175,9 @@ pub struct ModAddCommunity {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_add_community"]
|
#[table_name = "mod_add_community"]
|
||||||
pub struct ModAddCommunityForm {
|
pub struct ModAddCommunityForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub community_id: i32,
|
pub community_id: CommunityId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -179,8 +185,8 @@ pub struct ModAddCommunityForm {
|
||||||
#[table_name = "mod_add"]
|
#[table_name = "mod_add"]
|
||||||
pub struct ModAdd {
|
pub struct ModAdd {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
pub when_: chrono::NaiveDateTime,
|
pub when_: chrono::NaiveDateTime,
|
||||||
}
|
}
|
||||||
|
@ -188,7 +194,7 @@ pub struct ModAdd {
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "mod_add"]
|
#[table_name = "mod_add"]
|
||||||
pub struct ModAddForm {
|
pub struct ModAddForm {
|
||||||
pub mod_user_id: i32,
|
pub mod_person_id: PersonId,
|
||||||
pub other_user_id: i32,
|
pub other_person_id: PersonId,
|
||||||
pub removed: Option<bool>,
|
pub removed: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
use crate::schema::password_reset_request;
|
use crate::{schema::password_reset_request, LocalUserId};
|
||||||
|
|
||||||
#[derive(Queryable, Identifiable, PartialEq, Debug)]
|
#[derive(Queryable, Identifiable, PartialEq, Debug)]
|
||||||
#[table_name = "password_reset_request"]
|
#[table_name = "password_reset_request"]
|
||||||
pub struct PasswordResetRequest {
|
pub struct PasswordResetRequest {
|
||||||
pub id: i32,
|
pub id: i32,
|
||||||
pub user_id: i32,
|
|
||||||
pub token_encrypted: String,
|
pub token_encrypted: String,
|
||||||
pub published: chrono::NaiveDateTime,
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub local_user_id: LocalUserId,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Insertable, AsChangeset)]
|
#[derive(Insertable, AsChangeset)]
|
||||||
#[table_name = "password_reset_request"]
|
#[table_name = "password_reset_request"]
|
||||||
pub struct PasswordResetRequestForm {
|
pub struct PasswordResetRequestForm {
|
||||||
pub user_id: i32,
|
pub local_user_id: LocalUserId,
|
||||||
pub token_encrypted: String,
|
pub token_encrypted: String,
|
||||||
}
|
}
|
||||||
|
|
151
crates/db_schema/src/source/person.rs
Normal file
151
crates/db_schema/src/source/person.rs
Normal file
|
@ -0,0 +1,151 @@
|
||||||
|
use crate::{
|
||||||
|
schema::{person, person_alias_1, person_alias_2},
|
||||||
|
DbUrl,
|
||||||
|
PersonId,
|
||||||
|
};
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person"]
|
||||||
|
pub struct Person {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub private_key: Option<String>,
|
||||||
|
pub public_key: Option<String>,
|
||||||
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A safe representation of person, without the sensitive info
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person"]
|
||||||
|
pub struct PersonSafe {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person_alias_1"]
|
||||||
|
pub struct PersonAlias1 {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub private_key: Option<String>,
|
||||||
|
pub public_key: Option<String>,
|
||||||
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person_alias_1"]
|
||||||
|
pub struct PersonSafeAlias1 {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person_alias_2"]
|
||||||
|
pub struct PersonAlias2 {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub private_key: Option<String>,
|
||||||
|
pub public_key: Option<String>,
|
||||||
|
pub last_refreshed_at: chrono::NaiveDateTime,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Queryable, Identifiable, PartialEq, Debug, Serialize)]
|
||||||
|
#[table_name = "person_alias_1"]
|
||||||
|
pub struct PersonSafeAlias2 {
|
||||||
|
pub id: PersonId,
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<String>,
|
||||||
|
pub avatar: Option<DbUrl>,
|
||||||
|
pub banned: bool,
|
||||||
|
pub published: chrono::NaiveDateTime,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: DbUrl,
|
||||||
|
pub bio: Option<String>,
|
||||||
|
pub local: bool,
|
||||||
|
pub banner: Option<DbUrl>,
|
||||||
|
pub deleted: bool,
|
||||||
|
pub inbox_url: DbUrl,
|
||||||
|
pub shared_inbox_url: Option<DbUrl>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Insertable, AsChangeset, Clone)]
|
||||||
|
#[table_name = "person"]
|
||||||
|
pub struct PersonForm {
|
||||||
|
pub name: String,
|
||||||
|
pub preferred_username: Option<Option<String>>,
|
||||||
|
pub avatar: Option<Option<DbUrl>>,
|
||||||
|
pub banned: Option<bool>,
|
||||||
|
pub published: Option<chrono::NaiveDateTime>,
|
||||||
|
pub updated: Option<chrono::NaiveDateTime>,
|
||||||
|
pub actor_id: Option<DbUrl>,
|
||||||
|
pub bio: Option<Option<String>>,
|
||||||
|
pub local: Option<bool>,
|
||||||
|
pub private_key: Option<Option<String>>,
|
||||||
|
pub public_key: Option<Option<String>>,
|
||||||
|
pub last_refreshed_at: Option<chrono::NaiveDateTime>,
|
||||||
|
pub banner: Option<Option<DbUrl>>,
|
||||||
|
pub deleted: Option<bool>,
|
||||||
|
pub inbox_url: Option<DbUrl>,
|
||||||
|
pub shared_inbox_url: Option<Option<DbUrl>>,
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue